検索、xarg、awkの問題

検索、xarg、awkの問題

私はコマンドを持っています:

awk 'BEGIN{print "Name, Number"}/value/{print FILENAME, "," $8}' *.txt >> out.csv

ディレクトリ内のtxtファイルを参照し、値を解析し、ヘッダー(名前、番号)を含む最終的なcsvファイルを作成するのに最適です。

私の問題は「多すぎる」ということなので、findとxargを使って修正します。

find ./ -maxdepth 1 -type f -name '*.txt' | xargs awk 'BEGIN{print "Name, Number"}/value/{print FILENAME, "," $8}' | sed 's/\.\///g' >> out.csv

これは過去には効果がありましたが、今ではヘッダが最後のcsvファイルに複数回書き込まれることがあります。理由はわかりません。これはディレクトリ内のtxtファイルの総数に関連しているため、特定の数に達するとこれが発生しますが、わかりません。

ありがとうございます。

答え1

awk はファイルのバッチごとにfind呼び出されるため、BEGIN必要なすべてのファイルに対して 1 回ではなく、バッチごとに 1 回実行されます。ARGV[]すべてのファイルを引数として使用してawkを呼び出し、「引数が多すぎます」エラーが原因でシェルが失敗するのではなく、awkはすべてのファイルを入力として読み取るために読み込むファイルの内部配列を埋めることができます()。

find ./ -maxdepth 1 -type f -name '*.txt' |
awk '
    BEGIN { OFS=","; print "Name", "Number" }
    NR==FNR { ARGV[ARGC++]=$0; next }
    /value/ { print substr(FILENAME,3), $8 }
' - > out.csv

また、awkスクリプトからいくつかのことをクリーンアップし、sedのパイプを削除しました。 awkを使うときはsedは必要ないからです。上記のコマンドを呼び出すときに出力ファイルを追加するのではなく、最初から新しく作成したいと仮定したので、に変更し>>ました。>

上記は、ファイル名に改行文字が含まれていないと仮定しています。その場合は、GNUツールを使用して-print0コマンドの最後findRS="\0";awkコマンドのBEGIN部分に追加してください。また、ファイル名に次のエントリが含まれていない"場合は、出力が有効なCSVではないと仮定しますが、ファイル名に次のいずれかが含まれている場合は、「パラメータが多すぎます」という問題を除いて、最初のスクリプトは完全に機能します。これは間違いなく失敗します。いいえ。

答え2

グループコマンド(つまり、and内に含まれる)またはサブシェル内(つまり、and内に含まれる)でandを実行し、find実行する前にヘッダーを印刷します。コマンド・グループ全体またはサブシェルの出力を出力ファイルにリダイレクトします。awk{}()find

例えば:

{
  echo "Name,Number"
  find ./ -maxdepth 1 -type f -name '*.txt' -exec \
    awk -v OFS=, '
      FNR==1 { fn = FILENAME; sub(/^\.\//, "", fn };
     /value/ {print fn, $8}' {} +
} >> out.csv

メモ:

  1. man bash表示と検索Compound Commands
  2. ここではそうする必要はありません。たとえば、xargs検索オプションを使用します。-execfind ... -exec awk ... {} +
  3. awkには.BTWからファイルを削除する機能がsed組み込まれています。sub()./findgsub()/gsed

関連情報