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

34
42
11
6
2
99
...

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


当前回答

sed ':a;N;s/\n/+/;ta' file|bc

其他回答

这是另一个简单的句子

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

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

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

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

C总是以速度取胜:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    ssize_t read;
    char *line = NULL;
    size_t len = 0;
    double sum = 0.0;

    while (read = getline(&line, &len, stdin) != -1) {
        sum += atof(line);
    }

    printf("%f", sum);
    return 0;
}

1M数字的计时(与我的python答案相同的机器/输入):

$ gcc sum.c -o sum && time ./sum < numbers 
5003371677.000000
real    0m0.188s
user    0m0.180s
sys     0m0.000s

考虑到你需要通读整个文件,我不知道你是否能找到比这更好的。

$sum = 0;
while(<>){
   $sum += $_;
}
print $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

用+替换所有的新行,加一个0并把它发送给Ruby解释器不是更容易吗?

(sed -e "s/$/+/" file; echo 0)|irb

如果你没有irb,你可以把它发送到bc,但是你必须删除所有的换行符,除了最后一个(echo)。最好使用tr,除非您拥有sed的博士学位。

(sed -e "s/$/+/" file|tr -d "\n"; echo 0)|bc