我正在编写一个解析器,并且必须做一些奇特的事情。我试图不使用 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
.
.
.
、-
、|
、start
、end
都是用于视觉表示,我只需要它在列列表中:
6
3
7
.
.
.
我目前有一种方法可以做到这一点,即使用增量head -n $i
并tail -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}'
sum
awk 中从 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
$
这种方法有几个优点:
- 简单的
- 快速地
- 将数字分组与数学完全分开
- 正确处理 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