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

34
42
11
6
2
99
...

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


当前回答

这是另一个:

open(FIL, "a.txt");

my $sum = 0;
foreach( <FIL> ) {chomp; $sum += $_;}

close(FIL);

print "Sum = $sum\n";

其他回答

我还没有测试,但它应该工作:

cat f | tr "\n" "+" | sed 's/+$/\n/' | bc

如果bc不处理EOF和EOL,你可能必须在bc之前添加“\n”到字符串(比如通过echo)…

到目前为止,没有一个解决方案使用浆糊。这里有一个:

paste -sd+ filename | bc

如果文件有一个尾随换行符,尾随+将导致语法错误。通过移除后面的+来修复错误:

paste -sd+ fiilename | sed 's/+$//g' | bc

例如,计算Σn,其中1<=n<=100000:

$ seq 100000 | paste -sd+ | bc -l
5000050000

(对于好奇的人来说,seqn会在给定正数n的情况下打印从1到n的数字序列。)

在去:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    sum := int64(0)
    for scanner.Scan() {
        v, err := strconv.ParseInt(scanner.Text(), 10, 64)
        if err != nil {
            fmt.Fprintf(os.Stderr, "Not an integer: '%s'\n", scanner.Text())
            os.Exit(1)
        }
        sum += v
    }
    fmt.Println(sum)
}

对于Perl一行程序,它基本上与Ayman Hourieh回答中的awk解决方案是一样的:

 % perl -nle '$sum += $_ } END { print $sum'

如果您对Perl一行程序的功能感到好奇,可以将它们分离:

 %  perl -MO=Deparse -nle '$sum += $_ } END { print $sum'

结果是一个更冗长的程序版本,其形式是没有人会自己编写的:

BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    $sum += $_;
}
sub END {
    print $sum;
}
-e syntax OK

只是为了搞笑,我用一个包含1,000,000个数字(范围为0 - 9,999)的文件尝试了这个方法。在我的Mac Pro上,它几乎是立即返回的。这太糟糕了,因为我希望使用mmap会非常快,但它只是在同一时间:

use 5.010;
use File::Map qw(map_file);

map_file my $map, $ARGV[0];

$sum += $1 while $map =~ m/(\d+)/g;

say $sum;

这是另一个:

open(FIL, "a.txt");

my $sum = 0;
foreach( <FIL> ) {chomp; $sum += $_;}

close(FIL);

print "Sum = $sum\n";