私は、次のように、ディレクトリ名に基づいて名前付きASCIIテーブルを含む複数のディレクトリを持っています。
a1/a1.txt
a2/a2.txt
a3/a3.txt
a4/a4.txt
b1/b1.txt
b2/b2.txt
b3/b3.txt
b4/b4.txt
各ファイルの4列目の平均(so)と(so)を計算して4つの異なるファイルを選択し、a
平均が最も高いテーブルを別のディレクトリに移動します。b
a
a1.txt a2.txt a3.txt a4.txt
b
b1.txt b2.txt b3.txt b4.txt
したがって、次のような場合:
a1.txt average value = 1
a2.txt average value = 0.25
a3.txt average value = 2
a4.txt average value = 1.15
b1.txt average value = 3
b2.txt average value = 1.7
b3.txt average value = 0.25
b4.txt average value = 2
次に、a3.txt
およびをb1.txt
リモートディレクトリに移動する必要があります。
次のコードがあります。
for x in a b
do
RESULT=$(awk '{x+=$4} END{print x/NR, FILENAME}' ${x}[1-4]/${x}[1-4].txt | sort -n -r| head -1)
highest="$(echo $RESULT | cut -d ' ' -f1 )"
hifile="$(echo $RESULT | cut -d ' ' -f2 )"
echo "highest was $highest in $hifile"
cp "$hifile" "high_dis/${x}.txt"
done
ただし、このコードは4つのファイルの平均を計算し、最後のファイル(a4.txt
sum b4.txt
)をコピーします。
希望の出力を取得する方法を知っている人はいますか?
答え1
あなたの問題は次の事実によって引き起こされますawk はすべての入力ファイルを読み込んだ後にのみ END 節に到達します。。
ループの最初の行をfor
次に置き換えると問題が解決します。
RESULT=$(awk 'BEGIN{curr_f=FILENAME; nr=1} {if(curr_f!=FILENAME){if(mean > max_mean){max_mean=mean; f=curr_f} curr_f=FILENAME; nr=0; sum=0} } { sum+=$4; nr++; mean=sum/nr } END{if(mean>max_mean){print mean, FILENAME}else{print max_mean, f}}' ${x}[1-4]/${x}[1-4].txt )
答え2
私は少し異なるアプローチを使用し、awkで直接より多くのことを行います。まず、FNR
新しいファイルが処理されるたびに1を返し、awk
すべてのaファイルまたはbファイルを一度に提供するものを使用します。awk
$ for f in a b; do
awk '(FNR==1 && n>1){
av=x/n;if(av>max){
max=av;f=FILENAME
}
x=0; n=0
}
{x+=$4;n=FNR}
END{
if(x/n>max){print x/n,FILENAME}
else{print max,f}'
} "$f"[1..4]/"$f"[1..4].txt; done
18898.4 a3.txt
18806 b4.txt
これにより、平均が最大の2つのファイルを取得できます。これを移動するには、前のスクリプトの出力から値を削除し、ファイル名のみを保持してからコマンドに直接渡すだけですcp
。
$ cp -v $(for f in a b; do awk '(FNR==1 && n>1){av=x/n;if(av>max){max=av;f=FILENAME};x=0;n=0}{x+=$4;n=FNR} END{if(x/n>max) print x/n,FILENAME; else print max,f}' "$f"[1-4]/"$f"[1..4].txt; done) bar/
‘a3.txt’ -> ‘bar/a3.txt’
‘b4.txt’ -> ‘bar/b4.txt’
ファイル名にスペースまたはワイルドカードが含まれていると中断されます。