我有一堆目录,每个目录都包含一个与目录名称相应命名的 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
我想通过计算每个文件第四列的平均值(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
但这段代码只是计算四个文件的平均值,然后复制最后一个文件(a4.txt
和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
这为我们提供了具有最大平均值的两个文件。要移动它们,您可以简单地从先前脚本的输出中删除该值,仅保留文件名并将其直接传递给命令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’
请注意,如果您的文件名包含空格或通配符,这将会中断。