我有一个包含数千个数字的文件,每个数字都在自己的行上:
34
42
11
6
2
99
...
我想写一个脚本,它将打印文件中所有数字的总和。我有一个解决办法,但不是很有效。(运行需要几分钟。)我在寻找一个更有效的解决方案。有什么建议吗?
我有一个包含数千个数字的文件,每个数字都在自己的行上:
34
42
11
6
2
99
...
我想写一个脚本,它将打印文件中所有数字的总和。我有一个解决办法,但不是很有效。(运行需要几分钟。)我在寻找一个更有效的解决方案。有什么建议吗?
当前回答
用+替换所有的新行,加一个0并把它发送给Ruby解释器不是更容易吗?
(sed -e "s/$/+/" file; echo 0)|irb
如果你没有irb,你可以把它发送到bc,但是你必须删除所有的换行符,除了最后一个(echo)。最好使用tr,除非您拥有sed的博士学位。
(sed -e "s/$/+/" file|tr -d "\n"; echo 0)|bc
其他回答
为了好玩,让我们对其进行基准测试:
$ for ((i=0; i<1000000; i++)) ; do echo $RANDOM; done > random_numbers
$ time perl -nle '$sum += $_ } END { print $sum' random_numbers
16379866392
real 0m0.226s
user 0m0.219s
sys 0m0.002s
$ time awk '{ sum += $1 } END { print sum }' random_numbers
16379866392
real 0m0.311s
user 0m0.304s
sys 0m0.005s
$ time { { tr "\n" + < random_numbers ; echo 0; } | bc; }
16379866392
real 0m0.445s
user 0m0.438s
sys 0m0.024s
$ time { s=0;while read l; do s=$((s+$l));done<random_numbers;echo $s; }
16379866392
real 0m9.309s
user 0m8.404s
sys 0m0.887s
$ time { s=0;while read l; do ((s+=l));done<random_numbers;echo $s; }
16379866392
real 0m7.191s
user 0m6.402s
sys 0m0.776s
$ time { sed ':a;N;s/\n/+/;ta' random_numbers|bc; }
^C
real 4m53.413s
user 4m52.584s
sys 0m0.052s
5分钟后,我中止了sed运行
我一直在lua潜水,速度很快:
$ time lua -e 'sum=0; for line in io.lines() do sum=sum+line end; print(sum)' < random_numbers
16388542582.0
real 0m0.362s
user 0m0.313s
sys 0m0.063s
当我更新这个的时候,ruby:
$ time ruby -e 'sum = 0; File.foreach(ARGV.shift) {|line| sum+=line.to_i}; puts sum' random_numbers
16388542582
real 0m0.378s
user 0m0.297s
sys 0m0.078s
听从埃德·莫顿的建议:使用1美元
$ time awk '{ sum += $1 } END { print sum }' random_numbers
16388542582
real 0m0.421s
user 0m0.359s
sys 0m0.063s
Vs使用$0
$ time awk '{ sum += $0 } END { print sum }' random_numbers
16388542582
real 0m0.302s
user 0m0.234s
sys 0m0.063s
下面是一个使用python和生成器表达式的解决方案。在我破旧的笔记本电脑上测试了无数个数字。
time python -c "import sys; print sum((float(l) for l in sys.stdin))" < file
real 0m0.619s
user 0m0.512s
sys 0m0.028s
我更喜欢用R来表示:
$ R -e 'sum(scan("filename"))'
Perl 6
say sum lines
~$ perl6 -e '.say for 0..1000000' > test.in
~$ perl6 -e 'say sum lines' < test.in
500000500000
这是直接的Bash:
sum=0
while read -r line
do
(( sum += line ))
done < file
echo $sum