ディレクトリ内のすべてのファイルをループ処理したいです。
ファイルは次のように配置されます:
<Overall>4
other data
<Overall>2
other data
......
コードは以下のとおりです:
for file in .dat;
do
awk 'x+=sub(/<Overall>/,""){y+=$0} END{print FILENAME, y/x}' $file
done
これはファイル内の値の平均を出力しますが、私が望んでいるのは、スクリプトがあるディレクトリを引数として取り、そのディレクトリ内のすべての .dat ファイルに対して awk コマンドを実行することです。
次のコードを使ってみました:
for file in $1
しかし、エラーが発生します:
awk: cmd. line:1: fatal cannot open file `folder' for reading (No such file or directory)
これに加えて、平均値の出力を高いものから低いものの順に並べ替えられるようにしたいと考えています。
答え1
2つのバリエーション:
- ファイルをループし、
awk
各ファイルごとに1回呼び出すか、 - スクリプトにすべてのファイルを与え
awk
、それぞれの平均を計算して、計算の進行に合わせてレポートを作成します。
以下のソリューションのいずれかの結果のソートは、出力をパイプすることで実行できます。
sort -k2,2rn
これにより、2 番目のフィールド (平均) で逆の数値ソートが実行されます。
最初の解決策:
#!/bin/sh
for name in "$1"/*.dat; do
test -f "$name" || continue # skip non-files
awk -F '>' '/<Overall>/ { s+=$NF; n++ } END { print FILENAME, s/n }' "$name"
done
このスクリプトは、最初の、そして唯一のコマンドライン引数として、コマンドライン上のディレクトリ名を想定しています。スクリプトawk
は、文字列 を含むすべての行を検索し、その行のの後の値をOverall
( で) 合計します。最後に、平均がファイル名とともに出力されます。変数 には、に何かを追加した回数が保持されます。s
>
n
s
2 番目の解決策 (GNU Awk が必要):
#!/bin/sh
find "$1" -maxdepth 1 -type f -name '*.dat' \
-exec awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' {} +
このスクリプトは、最初のスクリプトと同様に、唯一のコマンド ライン引数としてディレクトリ名を必要とします。これを使用して、一度にできるだけ多くのファイルでスクリプトfind
を実行します。awk
.dat
このスクリプトは、各ファイルを処理した後、次のファイルの読み取りを開始する前に、awk
GNU Awk のENDFILE
トリガーを使用して計算された値を出力し、変数s
とをリセットします。n
これは次のようにも書かれるかもしれない。
#!/bin/sh
awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' "$1"/*.dat
しかし、これは"$1"/*.dat
ファイル名のリストが長くなりすぎないことに依存しています (また、各名前が通常のファイルである必要があり、これは上記のコマンドで保証されている.dat
ものです)。find
-type f