我有一个包含数千个数字的文件,每个数字都在自己的行上:

34
42
11
6
2
99
...

我想写一个脚本,它将打印文件中所有数字的总和。我有一个解决办法,但不是很有效。(运行需要几分钟。)我在寻找一个更有效的解决方案。有什么建议吗?


当前回答

这是另一个简单的句子

( echo 0 ; sed 's/$/ +/' foo ; echo p ) | dc

这假设数字是整数。如果你需要小数,试试

( echo 0 2k ; sed 's/$/ +/' foo ; echo p ) | dc

将2调整为所需的小数数。

其他回答

为了好玩,让我们对其进行基准测试:

$ 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

tcl中的一个:

#!/usr/bin/env tclsh
set sum 0
while {[gets stdin num] >= 0} { incr sum $num }
puts $sum

我不能只是路过……下面是我的Haskell俏皮话。它实际上是相当可读的:

sum <$> (read <$>) <$> lines <$> getContents

不幸的是,没有ghci -e来运行它,所以它需要main函数、打印和编译。

main = (sum <$> (read <$>) <$> lines <$> getContents) >>= print

为了澄清,我们读取整个输入(getContents),按行分割,读取为数字和和。<$>是fmap操作符-我们使用它而不是通常的函数应用程序,因为这一切都发生在IO中。Read需要一个额外的fmap,因为它也在列表中。

$ ghc sum.hs
[1 of 1] Compiling Main             ( sum.hs, sum.o )
Linking sum ...
$ ./sum 
1
2
4
^D
7

下面是一个奇怪的升级,让它与浮动一起工作:

main = ((0.0 + ) <$> sum <$> (read <$>) <$> lines <$> getContents) >>= print
$ ./sum 
1.3
2.1
4.2
^D
7.6000000000000005

这是直接的Bash:

sum=0
while read -r line
do
    (( sum += line ))
done < file
echo $sum

c++“俏皮话”:

#include <iostream>
#include <iterator>
#include <numeric>
using namespace std;

int main() {
    cout << accumulate(istream_iterator<int>(cin), istream_iterator<int>(), 0) << endl;
}