我有两列文件,第一列已排序,例如
0 107
1 1
1 141
2 22
3 1
3 222
4 65
5 1
5 53
6 79
我想要一个输出,第一列中没有重复的条目,第二列是重复的第一列值的第二列旧值的总和。我的尝试:awk '$1 != p{ if (NR>1) print p, s; p=$1; s=0} {s+=$2} END{print p, s}'
,输出
107
1 142
2 22
3 223
4 65
5 54
6 79
也就是说,0
第一行第一列的值没有显示出来。我遗漏了什么?最好有一行解决方案。
答案1
首先,我建议将 if 子句操作括在括号中。例如,下面很明显 if 子句仅适用于{print p,s}
,而不适用于p=$1
and s=0
:
awk '$1!=p{if(NR>1){print p,s};p=$1;s=0}{s+=$2}END{print p,s}'
虽然这只是表面上的,但不是一个错误。
你的错误在于没有注意到在比较中,未设置的变量将被视为0
和空字符串。对于文件的第一行,$1=0
。因此,$1!=p
是错误的对于第一行(因为p
未设置),这意味着p
当 awk 开始读取第二行时仍然未设置。
p
一个可能的解决方案是在程序启动时设置为空字符串:
awk 'BEGIN{p=""}$1!=p{if(NR>1){print p,s};p=$1;s=0}{s+=$2}END{print p,s}' file
awk '$1!=p{if(NR>1){print p,s};p=$1;s=0}{s+=$2}END{print p,s}' p="" file
现在,$1!=p
比较的是真的对于第一行,如0!=""
。
输出:
0 107
1 142
2 22
3 223
4 65
5 54
6 79
答案2
尝试:
awk '$1 != p && NR>1{print p, s; s=0} {p=$1; s+=$2} END{print p, s}'
怎么运行的
任何时候我们到达序列的末尾,$1 != p && NR>1
我们都会打印p, s
并重置s
回零。
对于每一行,我们将其设置为第一列,然后按第二列p
递增。s
在最后一行之后,我们打印p, s
。