最後のアンダースコア文字で文字列を切り取る方法は?

最後のアンダースコア文字で文字列を切り取る方法は?

次のファイルのリストがあります。

[root@ods1 backup]# ls -l
total 93892810
-rw-r----- 1 root root 651248 Feb 17 08:34  abc_def_g_17-02-2022.sql
-rw------- 1 root root 665248 Mar 23 08:46  bbc_23-03-2022.sql
-rw-r----- 1 root root 676992 Apr 04 16:52  zz_b_04-04-2022.sql

私が達成しなければならないことは次のとおりです。

abc_def_g
bbc
zz_b

私は成功せずにこれを試しました。

ls -l | awk '{print $9}' | cut -d '_' -f1-2

この目標をどのように達成できますか?最後の行まで一連のコマンドを取得します。_キャラクターは職業に依存しなければなりません。

編集:このコマンドはCentOS 8で実行されます。

答え1

到着解析されないlsloop、シンプルで構文を使用できますshell

for f in *; do echo "${f%_*}"; done

リストをさらに処理する必要がある場合(および配列で作業できるシェルがある場合)、項目を配列に追加できます。

tokens=()
for f in *; do tokens=("${tokens[@]}" "${f%_*}"); done
echo "${tokens[@]}"

あるいは、ループを使わずに配列を直接宣言します。

files=(*)
tokens=("${files[@]%_*}")
#or
for token in "${files[@]%_*}"; do echo "$token"; done

答え2

次のように試すことができます。

ls|awk -F_ '{NF-=1}1' OFS=_

ここでの秘密は、フィールド数を1つずつ減らすことです(最後のフィールドを削除)。

答え3

zshシェルから:

print -r -C1 -- *_*.sql(Ne['REPLY=${REPLY%_*}'])

*_*.sqlこれは、glob修飾子を使用して、最後の下線を含む最後の下線の後のすべての項目を削除し、指定されたglobパターンに一致する名前を変更します。実際の置換は標準パラメータ置換を使用して行われます。

結果文字列を使用して印刷以外の操作を実行するには、代わりにワイルドカードパターンを使用しますprint(たとえば、forループ内または他のコマンドの引数として)。print上記のコマンドをコマンド置換に入れないでください。

答え4

出力を解析しません。ls:

$ awk 'BEGIN{for (i=1;i<ARGC;i++) { f=ARGV[i]; sub(/_[^_]*$/,"",f); print f }; delete ARGV}' *
abc_def_g
bbc
zz_b

これは、ファイル名に改行文字やその他の文字が含まれている場合にも機能します。

関連情報