Bash命令对一列数字求和

Jub*_*bal 353 bash

我想要一个bash命令,我可以管道,将总和一列数字.我只想要一个快速的衬垫,它将做一些基本上像这样的事情:

cat FileWithColumnOfNumbers.txt | sum
Run Code Online (Sandbox Code Playgroud)

Dim*_*lov 780

使用现有文件:

paste -sd+ infile | bc
Run Code Online (Sandbox Code Playgroud)

使用stdin:

<cmd> | paste -sd+ | bc
Run Code Online (Sandbox Code Playgroud)

编辑:使用一些粘贴实现,从stdin读取时需要更明确:

<cmd> | paste -sd+ - | bc

  • 应该有一个徽章. (39认同)
  • 好吧,使用awk会更容易:`awk'END {print s} {s + = $ 8}'infile` :) (22认同)
  • 只是OS X的另一个FYI,我必须在粘贴命令的末尾添加一个 - 以便在OS X 10.6.8上工作. (14认同)
  • 就像一个FYI,`-s`选项是GNU`paste`; Mac OS X 10.7.4`paste`不支持它.但是,由于[`paste`]的POSIX 2008规范(http://pubs.opengroup.org/onlinepubs/9699919799/utilities/paste.html)支持`-s`,这是Mac OS X版本的缺陷. (5认同)
  • 使用`bc -l`,您甚至可以添加浮点数.使用`cut`,您可以从输入中选择列:`cat input.txt | cut -d'' - f 8 | 粘贴-sd + | bc -l`将在输入的第8列中添加所有浮点数(空格是字段分隔符). (4认同)
  • 对不起,各位贴爱好者。-1 因为太具体了。这仅在您的文件中只有数字时才有效。我几乎从来没有遇到过这种情况。谷歌“bash 添加列号”,你就到了这里。总是,我试图添加一个散布着其他数据的列(du 输出或类似的东西——我们说的是 bash,系统管理员的语言,对吧?)。Ghostdog 的 awk 答案适用于包含一列数字和其他列的任何数据。它不那么脆弱,几乎同样简洁,而且启动速度更快。 (3认同)
  • @Ben,在下面的帖子中你会找到_awk_和_Perl_解决方案. (2认同)
  • `&lt;命令&gt; | 粘贴-sd+-| bc`对我来说就像一个魔法。bash 命令行太棒了! (2认同)
  • 这有很多赞成票,但答案可以包括所有命令和开关实际上在做什么吗? (2认同)

gho*_*g74 171

我喜欢所选择的答案.但是,它往往比awk慢,因为需要2个工具来完成这项工作.

$ wc -l file
49999998 file

$ time paste -sd+ file | bc
1448700364

real    1m36.960s
user    1m24.515s
sys     0m1.772s

$ time awk '{s+=$1}END{print s}' file
1448700364

real    0m45.476s
user    0m40.756s
sys     0m0.287s
Run Code Online (Sandbox Code Playgroud)

  • awk是这项工作的正确工具!bc解决方案没问题,但是当您需要对两列进行求和或者过滤掉负数时会发生什么.使用awk,您可以轻松而明智地添加额外的逻辑,使用bc解决方案,您最终会通过另一个命令(cut或grep)进行管道传输 (4认同)
  • 好点子!在SunOS 5.8 bc甚至核心转储中有如此大的输入文件(请参阅下面的帖子). (2认同)
  • 我也会使用 awk,因为它允许通过执行 `awk 'BEGIN{s=0}{s+=$1}END{print s}'` 将 `s` 初始化为 0。在这种情况下,如果将空列通过管道输送到`paste | bc`,后一个管道将返回`0`而不是 null。(在某些情况下,空列可能是合法输入)。 (2认同)

Jon*_*ler 49

两行是否算在内?

awk '{ sum += $1; }
     END { print sum; }' "$@"
Run Code Online (Sandbox Code Playgroud)

然后你就可以在没有多余的'猫'的情况下使用它:

sum < FileWithColumnOfNumbers.txt
sum   FileWithColumnOfNumbers.txt
Run Code Online (Sandbox Code Playgroud)

FWIW:在MacOS X上,您可以使用单行:

awk '{ sum += $1; } END { print sum; }' "$@"
Run Code Online (Sandbox Code Playgroud)

  • 单线程awk适用于我尝试过的任何awk,而不仅仅是OS X. (6认同)

min*_*s23 44

以下命令将添加所有行(awk输出的第一个字段)

awk '{s+=$1} END {print s}' filename
Run Code Online (Sandbox Code Playgroud)

  • 这个适用于 mac OS 10.15 (2认同)
  • `命令| 粘贴 -s -d'+' - | bc` 也可以在 mac OS 上运行 (2认同)

Dim*_*lov 17

[对ghostdog74s评论的跟进]

bash-2.03$ uname -sr
SunOS 5.8

bash-2.03$ perl -le 'print for 1..49999998' > infile

bash-2.03$ wc -l infile
 49999998 infile

bash-2.03$  time paste -sd+ infile | bc
bundling space exceeded on line 1, teletype
Broken Pipe

real    0m0.062s
user    0m0.010s
sys     0m0.010s

bash-2.03$ time nawk '{s+=$1}END{print s}' infile
1249999925000001

real    2m0.042s
user    1m59.220s
sys     0m0.590s
bash-2.03$ time /usr/xpg4/bin/awk '{s+=$1}END{print s}' infile
1249999925000001

real    2m27.260s
user    2m26.230s
sys     0m0.660s

bash-2.03$ time perl -nle'
  $s += $_; END { print $s }
   ' infile
1.249999925e+15

real    1m34.663s
user    1m33.710s
sys     0m0.650s
Run Code Online (Sandbox Code Playgroud)

  • +1 指出 bc 版本中的核心转储。我犹豫是否要更改这个问题的“答案”,因为 bc 版本对我来说效果很好(我总共有 30 个数字)。 (2认同)

DVK*_*DVK 11

你可以使用bc(计算器).假设您的#s文件名为"n":

$ cat n
1
2
3
$ (cat n | tr "\012" "+" ; echo "0") | bc 
6
Run Code Online (Sandbox Code Playgroud)

tr所有换行符更改为"+"; 然后我们在最后一个加号后追加0,然后我们将表达式(1+2+3+0)传递给计算器

或者,如果您使用awk或perl,那么这是一个Perl单行程序:

$perl -nle '$sum += $_ } END { print $sum' n
6
Run Code Online (Sandbox Code Playgroud)

  • 对于 perl,这也有效: `perl -nle '$s+=$_}{print $s'` 它更简单一些。:) (2认同)

Pau*_*ce. 9

while read -r num; do ((sum += num)); done < inputfile; echo $sum
Run Code Online (Sandbox Code Playgroud)


t6d*_*t6d 5

使用for循环遍历您的文件…

sum=0; for x in `cat <your-file>`; do let sum+=x; done; echo $sum
Run Code Online (Sandbox Code Playgroud)

  • $(&lt;infile)中没有s的`cat` ::`; 不要让sum + = $ s; 完成&amp;&amp;回声$ sum` (2认同)

Joe*_*tti 5

如果你安装了 ruby

cat FileWithColumnOfNumbers.txt | xargs ruby -e "puts ARGV.map(&:to_i).inject(&:+)"
Run Code Online (Sandbox Code Playgroud)