awk命令用于对行对进行求和,并在特定条件下过滤掉

时间:2017-07-17 13:16:50

标签: bash awk

我有一个带有数字的文件,我想要对两行中的数字进行求和,然后在我的最后一步中,我想过滤出数量大于或等于3的“0”的行数总数。我写了一个小例子来说清楚:

这是我的文件(没有c的注释),它包含2对线(= 4行)和5列。

2 6 0 8 9  # pair 1.A
0 1 0 5 1  # pair 1.B
0 2 0 3 0  # pair 2.A
0 0 0 0 0  # pair 2.B

我需要总结一对线,所以我得到这样的东西(中间步骤)

2 7 0 13 10 # sum pair 1, it has one 0 
0 2 0 3 0   # sum pair 2, it has three 0 

然后我要打印原始行,但只有那些总和0(两行总和)低于3的那些,因此我应该打印出来:

2 6 0 8 9  # pair 1.A
0 1 0 5 1  # pair 1.B

因为第二对线的总和有三个0,所以应排除它

所以从第一个文件我需要得到最后一个输出。

到目前为止,我能够做的是对线对进行求和,计算零,并识别计数低于0的3,但我不知道如何打印这两行对SUM有贡献,我只能打印两行中的一行(最后一行)。这是我正在使用的awk:

  awk '
  NR%2 { split($0, a); next } 
  { for (i=1; i<=NF; i++) if (a[i]+$i == 0) SUM +=1; 
  if (SUM < 3) print $0; SUM=0 }' myfile 

(这就是我现在得到的)

0 1 0 5 1 # pair 1.B

谢谢!

3 个答案:

答案 0 :(得分:2)

另一种变体可能有助于避免某些输入情况下的循环迭代:

awk '!(NR%2){ zeros=0; for(i=1;i<=NF;i++) { if(a[i]+$i==0) zeros++; if(zeros>=3) next } 
     print prev ORS $0 }{ split($0,a); prev=$0 }' file

输出:

2 6 0 8 9
0 1 0 5 1

答案 1 :(得分:1)

好吧,经过多挖一点后,我发现打印上一行非常简单(我让自己变得复杂)

  awk '
  NR%2 { split($0, a) ; b=$0; next } 
  { for (i=1; i<=NF; i++) if (a[i]+$i == 0) SUM +=1; 
  if (SUM < 3) print b"\n"$0; SUM=0}' myfile

所以我只需将第一行保存在变量b中,并在条件有利时打印。 希望它也可以帮助其他人

答案 2 :(得分:1)

$ cat tst.awk
!(NR%2) {
    split(prev,p)
    zeroCnt = 0
    for (i=1; i<=NF; i++) {
        zeroCnt += (($i + p[i]) == 0 ? 1 : 0)
    }
    if (zeroCnt < 3) {
        print prev ORS $0
    }
}
{ prev = $0 }

$ awk -f tst.awk file
2 6 0 8 9
0 1 0 5 1