大文件的 awk 和 sum 行
Posted
技术标签:
【中文标题】大文件的 awk 和 sum 行【英文标题】:awk and sum rows for large files 【发布时间】:2016-10-08 01:14:58 【问题描述】:我有数百个文件要处理。每个文件包含数百万行。
示例文件内容:
---------------
12
3
5
---------------
8
0
5
---------------
1
5
56
4
---------------
我需要得到如下所示的输出(由前一个文件中的破折号分隔的数字总和):
20
13
66
我将while
、if
、else
与awk
结合使用,但if
/else
大大减慢了处理速度。
任何想法如何使用纯awk
来加速计算?
【问题讨论】:
你应该展示你的代码——while
和if
是在shell脚本中还是在awk
脚本中?无论如何,awk
脚本中不需要循环或if
条件。如果没有最后一行破折号,文件会结束吗?
wrt I used while, if, else
- 阅读 why-is-using-a-shell-loop-to-process-text-considered-bad-practice 和一个 shell 教程。还可以获取 Arnold Robbins 的《Effective Awk Programming, 4th Edition》一书。
样本文件内容是代表单个还是多个文件?
【参考方案1】:
你不需要 if/else 块,
$ awk 'FNR>1 && /^----/ print sum; sum=0; next sum+=$1' file1,2
20
13
66
20
13
66
例如对于您的输入文件 1 和文件 2 的副本。例如,您可能会一次运行一个或多个输入的总和前加上前缀
$ awk 'FNR==1block=0 FNR>1 && /^----/ print FILENAME, ++block, sum; sum=0; next
sum+=$1' file1,2
file1 1 20
file1 2 13
file1 3 66
file2 1 20
file2 2 13
file2 3 66
【讨论】:
绝对是awk to the rescue
时刻!祝大家好运。
对于这个问题,这些挑剔的东西并不直接相关,但对于现实世界,它们可能是。如果最后一个文件不以破折号行结尾,那么您将不会输出最后一个总和。解决这个问题很麻烦。如果一个文件不是以一行破折号结尾,而下一个文件不是以一行破折号开头,那么您将合并这两个总和。将第一行的破折号行添加到sum
似乎有点有趣——尽管awk
将其视为零已经足够好了。但是对于格式良好的输入,这很好。【参考方案2】:
$ awk '/^-+$/if (s!="") print s; s=""; next s+=$0' file
20
13
66
请注意 s 与 ""
的设置/比较,以区别处理它,如果其总和值为 0 与刚刚初始化为空字符串。
【讨论】:
【参考方案3】:另一种选择。我很好奇它是如何在速度方面叠加的
awk -v RS='\n-+\n' -F'\n' 'NF s=0; for(i=1; i<=NF; i++) s+=$i; print s' file ...
【讨论】:
由于多字符 RS,您应该提到它是 gawk 特定的。【参考方案4】:感谢大家花时间帮助我!与 while/if 条件相比,您的 awk 示例速度非常快。感谢您的链接也描述了原因。看来我创建了我能写的最糟糕的代码版本:-/
我的代码版本也可以,但速度非常慢:
sum=0
while read line
do
if [ "$line" = "---------------" ]; then
echo $sum
sum=0
else sum=`echo $line $sum | awk 'print $1 + $2'`
fi
done < input_file.txt
再次感谢大师!
【讨论】:
不仅速度很慢,而且在给定各种输入值和/或环境设置和/或运行它的目录的内容的情况下,它会破坏您的输出。不要在任何重要的事情上运行它。而是选择您获得的解决方案之一并执行此操作。你还问了Any ideas how to use pure awk to speed up calculations?
,所以你应该投反对票,因为你发布了你自己的解决方案,甚至没有按照你的要求做!以上是关于大文件的 awk 和 sum 行的主要内容,如果未能解决你的问题,请参考以下文章