Bash command to sum a column of numbers
我需要一个bash命令,我可以通过管道输入该命令,它将对一列数字求和。我只想要一个快速的一行程序,可以做一些基本上类似的事情:
1
| cat FileWithColumnOfNumbers.txt | sum |
- 相关:stackoverflow.com/q/3934423/376454
- 仅供参考,awk解决方案更容易记忆,速度大约快2倍(见这里和这里)。
使用现有文件:
使用STDIN:
编辑:对于一些粘贴实现,从stdin读取时需要更加明确:
| paste -sd+ - | bc
- 哦!我喜欢!+ 1
- 太棒了!+我也是!
- 我赞成简洁。
- 应该有一个徽章。
- +从我这里得到最简洁的解决方案!
- 与Fyi一样,-s选项在GNU paste中;Mac OS X 10.7.4 paste不支持该选项。但是,由于paste的posix 2008规范支持-s,这是mac os x版本中的一个缺陷。
- 这救了我的皮肤。这样的答案应该有+2。令人惊叹的。
- 仅仅是另一个操作系统x的fyi,我必须在粘贴命令的末尾添加a-,以便在操作系统x 10.6.8上工作。
- 用bc -l你甚至可以把浮点数相加。使用cut可以从输入中选择列:cat input.txt | cut -d ' ' -f 8 | paste -sd+ | bc -l将在输入的第8列中添加所有浮点数(空格为字段分隔符)。
- 好吧,用awk会更容易些:awk 'END { print s } { s += $8 }' infile。
- bc似乎不支持科学记数法。我有一些十进制数字,有些像2.345e-3。思想?Perl/Python?
- @本,在下面的线程中,您将找到awk和perl解决方案。
- 对不起,你们都是贴情人。-我说得太具体了。只有当您的文件中只有数字时,这才有效。我几乎从未遇到过这种情况。谷歌"bash添加列号"就可以了。总是,我试图添加一个散布着其他数据的列(du output或类似的东西——我们谈论的是bash,系统管理员的语言,对吧?).ghostdog的awk答案适用于任何包含数字列和其他列的数据。它不那么脆弱,几乎一样简洁,启动速度更快。
- 不得不增加浮点数bc -l给出了解析错误。使用octave而不是bc效果很好。
- @axelbregnsbo,它必须是十进制分隔符问题(,vs.),因为显然BC支持浮点计算。
- Paste和BC不会从盒子里出来,而awk会,所以我更喜欢awk。
- 以东十一〔29〕对我来说是一种魔力。巴什命令行摇滚!
- 仅当文件中只有一列时,此操作才有效。
- 我不知道粘贴命令。好把戏:
我喜欢选择的答案。然而,它往往比awk慢,因为这项工作需要两个工具。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $ 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 |
- 好点!在公元前5.8年的Sunos5.8bc上,即使核心转储也有如此大的输入文件(见下面我的文章)。
- awk是正确的工作工具!BC解决方案是可以的,但是当需要求和两列或者过滤掉负数时会发生什么。使用awk,您可以轻松、明智地添加额外的逻辑,使用bc解决方案,您最终将通过管道传递另一个命令(cut或grep)。
- 拉杜洛夫。谢谢。不知道Solaris的BC会在大的输入上犹豫。
- 我也会使用awk,因为它允许通过执行awk 'BEGIN{s=0}{s+=$1}END{print s}'将s初始化为0。在这种情况下,如果一个空列被导入paste | bc中,后者将返回0而不是NULL。(有些情况下,空列是合法输入)。
- 这比所选择的答案更通用、更快、更不脆弱。+1作为"如何在文件中添加数字列"的最佳答案。所选答案包括"如何在文件中仅添加数字列"。
两行数吗?
1 2
| awk '{ sum += $1; }
END { print sum; }'"$@" |
然后你就可以不用多余的"猫"了:
1 2
| sum < FileWithColumnOfNumbers.txt
sum FileWithColumnOfNumbers.txt |
fwiw:在MacOS X上,你可以用一个一行程序:
1
| awk '{ sum += $1; } END { print sum; }'"$@" |
- @jskagz-请参阅我的答案,以获得更短/更简单的perl版本:)
- 一行awk适用于我尝试过的任何awk,不仅仅是OS X
- @安哈默:我再也不能访问第7版Unix及其版本的awk。我不知道这条线是否在那里起作用,但当我学习awk时,我没有试过。您可能是对的;所有当前版本的awk都可能支持一行程序。
- $@是做什么的?这似乎对我使用PBPaste_awk没有影响。
- @davidmann:"$@"在脚本中用于表示脚本的所有参数,如果没有参数,则为Nothing/None。如果在pbpaste | awk …中使用awk,只需省略"$@"(尽管它通常不会造成损坏;终端上的大多数交互shell没有‘位置参数’,所以"$@"不是什么)。但是,如果您有一个shell脚本sumcol1.sh,那么添加"$@"是明智的—然后您可以使用pbpaste | sumcol1.sh或类似的脚本,它会正常工作,sumcol1.sh file1 file2也会正常工作。
以下命令将添加所有行(awk输出的第一个字段)
1
| awk '{s+=$1} END {print s}' filename |
[Ghostdog74s评论的后续报道]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| 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 |
- +1用于在BC版本中指出coredump。我不愿改变这个问题的"答案",因为BC版本对我来说很好(我总共有30个数字)。
- +1对于Perl版本-在我的Ubuntu 12.04上最快
- +1对于处理浮点数字的Perl版本。另外,为了确切地了解我正在寻找的内容,这里总结了一个特定的列(从零开始索引的列2):perl -nle '$s += (split)[2]; END { print $s }' foo.txt或使用管道:cat foo.txt | perl -nle '$s += (split)[2]; END { print $s }'。
- 另外:paste -sd+ -|perl -nle 'print eval'。
您可以使用BC(计算器)。假设您的文件名为"n":
1 2 3 4 5 6
| $ cat n
1
2
3
$ (cat n | tr"\012""+" ; echo"0") | bc
6 |
tr将所有换行改为"+",然后在最后一个加号后附加0,然后将表达式(1+2+3+0传送到计算器。
或者,如果您可以使用awk或perl,这里有一个perl一行程序:
1 2
| $perl -nle '$sum += $_ } END { print $sum' n
6 |
- 对于Perl来说,这也是可行的:perl -nle '$s+=$_}{print $s'有点简单。:)
1
| while read -r num; do ((sum += num)); done < inputfile; echo $sum |
- 如果你有很多数字要添加,这就不太好了:使用@radulov的文件,这需要花费10M28秒(Ubuntu12.04)。Perl解决方案需要11s、AWK 13s和BC 37s。
- @另一方面,如果没有很多数字可以添加(jskagz告诉他需要的是30个数字),这种方式是最快的,因为没有分叉!
- @尽管只有一把叉子,但技术上的说法是正确的。另一方面,对于30个数字来说,速度有点无关紧要-最好使用您最熟悉的工具,如bash(:
如果安装了Ruby
1
| cat FileWithColumnOfNumbers.txt | xargs ruby -e"puts ARGV.map(&:to_i).inject(&:+)" |
使用for循环迭代您的文件…
1
| sum=0; for x in `cat <your-file>`; do let sum+=x; done; echo $sum |
- 无cat:for s in $(< infile); do let sum+=$s ; done && echo $sum。
1
| [root@pentest3r ~]# (find / -xdev -size +1024M) | (while read a ; do aa=$(du -sh $a | cut -d"." -f1 ); o=$(( $o+$aa )); done; echo"$o";) |
- 对于这个问题,有一部分答案隐藏在一个相当模糊的脚本中,这个脚本可以找到大文件,并分别在每个文件上运行du,这既痛苦又不重要。另一个较旧的答案提供了相同的"仅用外壳求和"解决方案。由于没有解释和重复另一个答案,也没有主题外的编码,保留这个答案确实没有任何好处。