shell - shell命令来求和, 每行一个整数?

  显示原文与译文双语对照的内容

我正在寻找一个命令,该命令将接受多行文本,每行包含一个整数,并输出这些整数的和。

作为一些背景,我有一个日志文件,其中包括计时测量,所以通过grepping的相关行,以及一些 sed 格式,我可以列出该文件中的所有计时。 为了进行最后的sum,我也希望能计算出图像的但是,我可以和我的大脑开始空白,因为变成了任何命令通过管道命令使用这里中间输出 to. 过去我一直使用 expr,但除非它在trac模式下运行,否则我认为它不会处理这个( 即使这样,也会很棘手) 。

我错过了什么鉴于有几种方法可以实现这一点,我很乐意阅读( 和 upvote )的任何方法,即使其他人已经发布了一个不同的解决方法。

相关问题:在Unix上计算一列输出的最短命令? ( 片尾 @Andrew )


的更新: 哇,就像预期的,这里有一些不错的答案。 看起来我一定要把awk作为一个command-line工具更深入地检查 !

时间:

awk的一点应该做?


awk '{s+=$1} END {print s}' mydatafile

注意:某些版本的awk有一些奇怪的行为如果你要添加超过 2 ^31 ( 2147483647 )的任何内容- 请参阅注释了解更多背景信息。 一个建议是使用printf而不是打印 awk '{s+=$1} END {printf"%.0f", s}' mydatafile

粘贴通常合并多个文件的行,但也可以用来将文件的各行转换为单行。 分隔符标志允许你将x+x类型方程传递给 bc 。


paste -s -d+ infile|bc


dc -f infile -e '[+z1<r]srz1<rp'

编辑:因为这个答案获得了这么多的投票"对于模糊",下面是一个详细的解释:

表达式 [+z1<r]srz1<rp执行以下操作:


[ interpret everything to the next ] as a string
 + push two values off the stack, add them and push the result
 z push the current stack depth
 1 push one
 <r pop two values and execute register r if the original top-of-stack (1)
 is smaller
] end of the string, will push the whole thing to the stack
sr pop a value (the string 上面) and store it in register r
z push the current stack depth again
1 push 1
<r pop two values and execute register r if the original top-of-stack (1)
 is smaller
p print the current top-of-stack

作为 pseudo-code:

  1. 将"add_top_of_stack"定义为:
    1. 删除堆栈中的两个顶部值并将结果添加回去
    2. 如果堆栈有两个或者多个值,请递归运行"add_top_of_stack"
  2. 如果堆栈有两个或者多个值,请运行"add_top_of_stack"
  3. 打印结果,现在只剩下堆栈中剩下的项目

为了真正理解 dc的简单和强大,下面是一个工作的python 脚本,它实现了 dc的一些命令,并执行了上述命令的python 版本:


### Implement some commands from dc
registers = {'r': None}
stack = []
def add():
 stack.append(stack.pop() + stack.pop())
def z():
 stack.append(len(stack))
def less(reg):
 if stack.pop() <stack.pop():
 registers[reg]()
def store(reg):
 registers[reg] = stack.pop()
def p():
 print stack[-1]

### Python version of the dc command 上面

# The equivalent to -f: read a file and push every line to the stack
import fileinput
for line in fileinput.input():
 stack.append(int(line.strip()))

def cmd():
 add()
 z()
 stack.append(1)
 less('r')

stack.append(cmd)
store('r')
z()
stack.append(1)
less('r')
p()

我将在常用的解决方案中提出一个重大警告:


awk '{s+=$1} END {print s}' mydatafile # DO NOT USE THIS!!

这是因为在这个表单中awk使用了一个 32位有符号整数表示: 超过 2147483647 ( 例如,2 ^31 )的总和会溢出。

更一般的答案( 用于求和整数) 是:


awk '{s+=$1} END {printf"%.0f", s}' mydatafile # USE THIS INSTEAD

P.S 。我希望评论第一个答案,但我没有足够的声誉。

...