ディレクトリを繰り返し、特定のパターンの横に合計値を生成して平均を生成します。

ディレクトリを繰り返し、特定のパターンの横に合計値を生成して平均を生成します。

ディレクトリ内のすべてのファイルを繰り返したいです。

ファイルの設定は次のとおりです。

<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つのバリエーション:

  1. ファイルを繰り返し、awk各ファイルに対して1回呼び出すか、
  2. スクリプトに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(in)の後の値を合計します。最後に、平均値がファイル名とともに出力されます。この変数は、私たちが何かを追加した回数を保持します。s>ns


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

関連情報