私はコマンドを持っています:
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
コマンドの最後find
とRS="\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
メモ:
man bash
表示と検索Compound Commands
- ここではそうする必要はありません。たとえば、
xargs
検索オプションを使用します。-exec
find ... -exec awk ... {} +
- awkには.BTWからファイルを削除する機能が
sed
組み込まれています。sub()
./
find
gsub()
/g
sed