将每 5 行整数相加

将每 5 行整数相加

我正在编写一个解析器,并且必须做一些奇特的事情。我试图不使用 python,但此时我可能不得不使用。

给定一个看起来像这样的 STDOUT:

1
0
2
3
0
0
1
0
0
2
0
3
0
4
0
5
0
2
.
.
.

对于 100,000 行。我需要做的就是每 5 加起来,如下所示:

1 - start
0 |
2 | - 6 
3 |
0 - end
0 - start
1 |
0 | - 3
0 |
2 - end
0 - start
3 |
0 | - 7
4 |
0 - end
5 
0 
2 
. 
.
.

-|startend都是用于视觉表示,我只需要它在列列表中:

 6
 3
 7
 .
 .
 .

我目前有一种方法可以做到这一点,即使用增量head -n $itail -n 5从列表中删除 5 行,然后将paste -sd+ - | bc所有值相加。但这太慢了,因为有 100,000 行。

我怎样才能做得更好?

答案1

cat numbers.txt | awk '{sum += $1; if (NR % 5 == 0) {print sum; sum=0}} END {if (NR % 5 != 0) print sum}'

sumawk 中从 0 开始。每隔第五行,它会打印出当前的数字总和,然后将总和重置为零并继续接下来的五行。最后END的 处理文件中行数不是 5 的倍数的边缘情况,例如,如果文件中有 18 行,它将打印最后 3 行的总和。当行数是五的倍数时,它还可以处理不打印不需要的零的边缘情况。

答案2

和一个 shell 循环(无错误检查;假设是 5 的偶数倍):

while read a; do read b; read c; read d; read e; echo $((a+b+c+d+e)); done < input

答案3

sed '$!N;$!N;$!N;$!N;s/\n/+/g' list.txt | bc

示范:

$ seq 33 | sed '$!N;$!N;$!N;$!N;s/\n/+/g'
1+2+3+4+5
6+7+8+9+10
11+12+13+14+15
16+17+18+19+20
21+22+23+24+25
26+27+28+29+30
31+32+33
$ seq 33 | sed '$!N;$!N;$!N;$!N;s/\n/+/g' | bc
15
40
65
90
115
140
96
$ 

这种方法有几个优点:

  1. 简单的
  2. 快速地
  3. 将数字分组与数学完全分开
  4. 正确处理 0 行、1 行、5n 行和非 5 行的倍数的情况

如果你想放弃额外的(例如,在上面的例子中放弃31到33),你可以取消所有条件$!;这是更简单的命令,也是我的第一次尝试:

$ seq 33 | sed 'N;N;N;N;s/\n/+/g'
1+2+3+4+5
6+7+8+9+10
11+12+13+14+15
16+17+18+19+20
21+22+23+24+25
26+27+28+29+30
$ 

答案4

首先因为这只需要 xargs:

<file xargs -rn5 perl -e 'foreach(@ARGV){$a+$_};print $a,"\n"'

但为了速度,你真的想尽量减少解释器调用的数量,所以我会使用

perl -e 'while(!eof(ARGV){print <>+<>+<>+<>+<>,"\n"}' file

相关内容