shell中多个文件的平均值
我想计算15个文件的平均值:-ifile1.txt,ifile2.txt,…,ifile15.txt。每个文件的列数和行数相同。部分数据看起来像shell中多个文件的平均值,shell,unix,awk,mean,Shell,Unix,Awk,Mean,我想计算15个文件的平均值:-ifile1.txt,ifile2.txt,…,ifile15.txt。每个文件的列数和行数相同。部分数据看起来像 ifile1.txt ifile2.txt ifile3.txt 3 5 2 2 . 1 2 1 3 . 4 3 4 1 . 1 4 2 1 . 1 3 0 2 . 5 3 1 5 . 4 6 5 2 . 2 5 5 1 . 3 4 3 1
ifile1.txt ifile2.txt ifile3.txt
3 5 2 2 . 1 2 1 3 . 4 3 4 1 .
1 4 2 1 . 1 3 0 2 . 5 3 1 5 .
4 6 5 2 . 2 5 5 1 . 3 4 3 1 .
5 5 7 1 . 0 0 1 1 . 4 3 4 0 .
. . . . . . . . . . . . . . .
我想找到一个新的文件,它将显示这15个文件的平均值
ofile.txt
2.66 3.33 2.33 2 . (i.e. average of 3 1 4, average of 5 2 3 and so on)
2.33 3.33 1 2.66 .
3 5 4.33 1.33 .
3 2.33 4 0.66 .
. . . . .
我尝试了以下内容,但出现了错误
awk'{for (i=1; i<=NF; i++)} rows=FNR;cols=NF} END
{for (i=1; i<=rows; i++){for (j=1; j<=cols; j++)
s+=$i;print $0,s/NF;s=0}}' ifile* > ofile.txt
awk'{for(i=1;i在读取原始文件时,您需要将字段的总和保存到一个数组中。您不能在END
块中访问$0
和i
,因为那时没有输入行
awk '{rows=FNR; cols=NF; for (i = 1; i <= NF; i++) { total[FNR, i] += $i }}
FILENAME != lastfn { count++; lastfn = FILENAME }
END { for (i = 1; i <= rows; i++) {
for (j = 1; j <= cols; j++) {
printf("%s ", total[i, j]/count)
}
printf("\n")
}
}' ifile* > ofile.txt
awk'{rows=FNR;cols=NF;for(i=1;i如所述:
awk'{for (i=1; i<=NF; i++)} rows=FNR;cols=NF} END
…
考虑到问题中的三个数据文件:
ifile1.txt
3 5 2 2
1 4 2 1
4 6 5 2
5 5 7 1
1 2 1 3
1 3 0 2
2 5 5 1
0 0 1 1
4 3 4 1
5 3 1 5
3 4 3 1
4 3 4 0
ifile2.txt
3 5 2 2
1 4 2 1
4 6 5 2
5 5 7 1
1 2 1 3
1 3 0 2
2 5 5 1
0 0 1 1
4 3 4 1
5 3 1 5
3 4 3 1
4 3 4 0
ifile3.txt
3 5 2 2
1 4 2 1
4 6 5 2
5 5 7 1
1 2 1 3
1 3 0 2
2 5 5 1
0 0 1 1
4 3 4 1
5 3 1 5
3 4 3 1
4 3 4 0
我展示的脚本产生了:
2.666667 3.333333 2.333333
2.333333 3.333333 1.000000
3.000000 5.000000 4.333333
3.000000 2.666667 4.000000
如果要将小数位数控制为2,请使用%.2f
代替%f
$ { head -n1 ifile1.txt; paste ifile*.txt;} | awk 'NR==1{d=NF; next;} {for (i=1;i<=d;i++) {s=0; for (j=i;j<=NF;j+=d) s+=$j; printf "%.2f%s",s/(NF/d),j==NF+d?"\n":"\t";}}'
2.67 3.33 2.33 2.00
2.33 3.33 1.00 2.67
3.00 5.00 4.33 1.33
3.00 2.67 4.00 0.67
|
管道符号使上述命令的输出作为输入发送到awk。依次寻址每个awk命令:
NR==1{d=NF;next;}
对于第一行,我们将列数保存在变量d
中。然后,我们跳过其余命令,从输入的下一行开始
for(i=1;该错误消息可能有助于某人回答您。您为什么试图访问END
块中的$0
和$i
?在您读取完所有文件后运行该块,当前没有要处理的记录。如前所述(awk'{for(i=1;我不知道它是否只是GNU awk
的东西(我使用它),但是FNR
和NF
的值在END{}
块中仍然有效-这样就不需要单独处理这些变量(至少在GNU awk
中).1它不应该只是GNUawk
的一个特性;最后一个文件的最后一行的信息也可能在POSIX标准awk
中提供。也就是说,我可能会增强代码以发现不正确的输入文件-列太多或太少,或行太多或太少。我根本不信任用户,包括我自己,不要滥用系统。GIGO很好,但是发现垃圾进入可以避免问题。检查POSIX规范;它明确地说FNR和NF都保留结束块中最后一个文件最后一行的值。