次のコードを使用して、一連のテキスト ファイル (foo*.txt) から情報を抽出しています。
for file in foo*.txt; do
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar.csv
done
このコメントは、一連のファイル (foo*.txt) から必要な数字を出力します。ファイル名 (csv ファイルの 1 つの列) と数字 (csv ファイルの次の列) の両方を出力しようとすると、ターミナルで次の操作を試しました。
for file in foo*.txt; do
echo $file
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar2.csv
done
これは、ターミナルにファイル名を出力します。 csv ファイルには必要な数字が含まれています。 ファイル名が csv ファイルの 1 つの列に出力され、抽出された数字が次の列に出力されるように、このコードを変更するにはどうすればよいでしょうか。
このコードのもう 1 つの問題は、ソートの問題です。たとえば、ファイル名 foo_01_s.txt、foo_02_s.txt、foo_03_s.txt...foo_100_s.txt を考えてみましょう。情報を抽出したい場合 (上記のコメントを使用)、最後のファイル (foo_100_s.txt) は foo_99_s.txt の後には来ません。
Python/Perl を使用したソリューションも役立ちます。
答え1
>>
は、現在のコマンドの一部のみをリダイレクトすることを理解する必要があります。基本的には、 で始まりgrep
、数回パイプされたコマンドの結果である数値だけです。echo $file
は別のコマンド ( を使用;
) であるため、通常は stdout にリダイレクトされます。ループ全体の後にリダイレクトするだけです。
for file in foo*.txt; do
echo $file
grep "some_text" $file | tail -n5 | awk '{print $2}'
done > bar2.csv
ファイルを「バージョン」で並べ替えたい場合 (これは適切な名前です)、並べ替え後にファイルを一覧表示できます。
for file in $(ls foo*.txt | sort -V); do
小さなものを素早く実行するには(約 1000 ファイルで数分)、これで十分でしょう。
編集
あなたのコメントに従って、いくつかの解決策があります。あなたが望んでいるのは次のようなことだと思います:
file1 1
2
3
など。を削除しecho
てエコー行を修正するだけです。
for file in foo*.txt; do
grep "some_text" $file | tail -n5 | awk -v f=$file '{if(NR==1) {printf("%-20s %-5s\n",f,\$2)} else {printf("%-20s %-5s\n","",$2)}}'
done > bar2.csv
awk
印刷は に任せています。 を使用すると-v
、 に変数を渡すことができますf
。 印刷については、シェルでprintf
使用できる構文に慣れman printf
てください。基本的に、2 つのフィールドを想定しています。1 つは 20、もう 1 つは 5、その間にスペースがあります。負の符号は左揃えです。試してみてください。これで最初の問題は解決しました。これで、その 1 行をパイプできるようになったからです。
ファイルを次のようにしたい場合:
file1,1
file1,2
...
file2,1
if
私のステートメントでは、を削除するawk
か、最初のソリューションをechoのままにして、
echo -n "$file,"
ここで-n
、改行は印刷されません。