我想循环遍历目录中的所有文件。
文件的设置如下:
<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
两种变体:
- 循环文件并
awk
为每个文件调用一次,或者 - 为脚本提供
awk
所有文件,让它计算每个文件的平均值并在运行过程中进行报告。
对以下任何解决方案的结果进行排序可以通过将其输出通过管道来完成
sort -k2,2rn
这对第二个字段(平均值)进行反向数字排序。
第一个解决方案:
#!/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
第二种解决方案(需要 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
)。