我刚接触awk。
我正在尝试编写一个脚本,该脚本使用一个输入文件,找到第三列的总和,然后打印第1列,第2列,然后打印标准化的第三列。但是,当我执行此操作时,似乎只在输入文件的最后一行执行此操作。我想我缺少有关“ END”工作原理的信息。有提示吗?
谢谢!
BEGIN {
col= ARGV[2]
ARGV[2] = ""
}
{s1 += $3}
END { if (NR > 0){
print s1;
print $1, $2, $3/s1
}
}
输入:
0 2 8.98002e-05
1 0 5.66203e-05
2 2 2.20586e-05
3 2 5.31672e-05
4 2 2.17192e-07
5 26 3.67908e-06
6 1 1.0385e-05
7 1 7.78022e-05
8 0 5.47272e-05
9 1 6.34726e-05
10 1 0.000105879
11 1 4.77847e-05
12 0 3.05258e-05
13 0 5.53268e-05
14 1 7.8916e-05
15 1 3.02601e-05
16 1 3.81807e-05
s1:0.000818803
OUTPUT:
0.000818803
0 2 0.109673
0.000818803
1 0 0.0691501
0.000818803
2 2 0.0269401
0.000818803
3 2 0.0649328
0.000818803
4 2 0.000265256
0.000818803
5 26 0.00449324
0.000818803
6 1 0.0126831
0.000818803
7 1 0.0950194
0.000818803
8 0 0.0668381
0.000818803
9 1 0.0775188
0.000818803
10 1 0.129309
0.000818803
11 1 0.0583592
0.000818803
12 0 0.037281
0.000818803
13 0 0.0675703
0.000818803
14 1 0.0963797
0.000818803
15 1 0.0369565
0.000818803
16 1 0.0466299
答案 0 :(得分:0)
为此,您必须通过记录进行两次遍历。一种方法是按如下所示的第一种方法读取文件本身两次。
第一遍只是累积s1
中第3列的总数。第二遍打印前两列和规范化的第三列。
请注意,您必须在命令行上提供两次文件,以便awk对其进行两次处理!
$ awk 'NR == FNR {s1 += $3; next} {print $1, $2, $3/s1}' file file
0 2 0.109673
1 0 0.0691501
2 2 0.0269401
3 2 0.0649329
4 2 0.000265256
5 26 0.00449324
6 1 0.0126832
7 1 0.0950195
8 0 0.0668381
9 1 0.0775188
10 1 0.12931
11 1 0.0583592
12 0 0.037281
13 0 0.0675704
14 1 0.0963798
15 1 0.0369565
16 1 0.0466299
另一种更接近尝试的方式是只读取一次文件,同时将所有行信息都保存在内存中,同时对第3列求和。
然后在END
块中,该块在读取所有记录并完全累加后运行,您遍历数组以打印出结果。
awk ' { s1 += $3; a[NR] = $1 OFS $2; b[NR] = $3 }
END { for (i=1; i<=NR; ++i) print a[i], b[i] / s1 }' file
第二种方法的明显缺点是要使用更多的内存-实际上,如果文件很大,这种方法甚至是不可行的。
如果您还不熟悉NR == FNR
构造,请参见What is "NR==FNR" in awk?。另请参见https://backreference.org/2010/02/10/idiomatic-awk/上有关“双文件处理”的部分。