我正在寻找一个命令,它将接受多行文本作为输入,每行包含一个整数,并输出这些整数的总和。
背景说明:我有一个日志文件,其中包括时间测量。通过grep相关行和一些sed
重新格式化,我可以列出该文件中的所有计时。我想计算出总时间。我可以将此中间输出传输到任何命令以进行最终求和。我过去总是使用expr
,但是除非它以RPN模式运行,否则我认为它无法处理这个问题(即使是在RPN模式下也很棘手)。
如何获得整数的总和?
我正在寻找一个命令,它将接受多行文本作为输入,每行包含一个整数,并输出这些整数的总和。
背景说明:我有一个日志文件,其中包括时间测量。通过grep相关行和一些sed
重新格式化,我可以列出该文件中的所有计时。我想计算出总时间。我可以将此中间输出传输到任何命令以进行最终求和。我过去总是使用expr
,但是除非它以RPN模式运行,否则我认为它无法处理这个问题(即使是在RPN模式下也很棘手)。
如何获得整数的总和?
用一点awk就可以了吗?
awk '{s+=$1} END {print s}' mydatafile
注意:如果您要添加的内容超过2^31(2147483647),某些版本的awk可能会有一些奇怪的行为。更多背景信息请参见评论。一个建议是使用printf
而不是print
:
awk '{s+=$1} END {printf "%.0f", s}' mydatafile
ls $@ | xargs -i pdftk {} dump_data | grep NumberOfPages | awk '{s+=$2} END {print s}'
- flying sheepawk '{s+=$1} END {printf "%.0f", s}' mydatafile
。 - Giancarlo SportelliPaste通常会合并多个文件的行,但也可以用于将文件的单个行转换为单个行。分隔符标记允许您将x+x类型的方程传递给bc。
paste -s -d+ infile | bc
或者,当从标准输入进行管道传输时,
<commands> | paste -s -d+ - | bc
paste
可以使用短横线“-”作为文件名 - 这将允许您将数字从命令输出管道到paste的标准输出,无需先创建文件: <commands> | paste -sd+ - | bc
- George-
,不过如果你想要将文件和标准输入合并在一起,它会很有用。 - Alois Mahdal$ python -c "import sys; print(sum(int(l) for l in sys.stdin))"
python -c"import sys; print(sum(map(int, sys.stdin)))"
,它的作用是将标准输入中的数字相加,并输出结果。 - jfsfind . -name '*.epub' -exec stat -c %s '{}' \; | python -c "import sys; nums = [int(n) for n in sys.stdin if int(n) < 10000000]; print(sum(nums)/len(nums))"
。 - Paul Whippimport sys; print(sum(int(''.join(c for c in l if c.isdigit())) for l in sys.stdin))
- Granitosaurus我会在通常被认可的解决方案上加上一个大警告:
awk '{s+=$1} END {print s}' mydatafile # DO NOT USE THIS!!
那是因为awk在这种形式下使用32位有符号整数表示:对于总和超过2147483647(即2的31次方)的情况,它将发生溢出。
更一般的答案(用于整数求和)是:
awk '{s+=$1} END {printf "%.0f\n", s}' mydatafile # USE THIS INSTEAD
echo -e "2147483647 \n 100" |awk '{s+=$1}END{print s}'
命令会输出 2147483747
。 - Xen2050echo 999999999999999999 | awk '{s+=$1} END {printf "%.0f\n", s}'
会输出 1000000000000000000
。 - phemmer%ld
放在哪里?我尝试了echo -e "999999999999999999" | awk '{s+=$1} END {printf "%ld\n", s}'
,但它仍然产生了1000000000000000000
。 - Josh简单的bash:
$ cat numbers.txt
1
2
3
4
5
6
7
8
9
10
$ sum=0; while read num; do ((sum += num)); done < numbers.txt; echo $sum
55
num
是在哪里定义的?我相信它与< numbers.txt
表达式有关,但不清楚具体是怎么回事。 - Atcoldnum
在 while 表达式中被定义。while read XX
的意思是“使用 while
读取一个值,然后将该值存储在 XX
中”。 - aggregate1166877dc -f infile -e '[+z1<r]srz1<rp'
注意,以减号为前缀的负数应该被翻译成dc
使用_
前缀而不是-
前缀。例如,通过 tr '-' '_' | dc -f- -e '...'
。
[+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 above) 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
伪代码如下:
为了真正理解 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 above
# 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()
(echo "0"; sed 's/$/ +/' inp; echo 'pq')|dc
。 - ikrabbedc -e '0 0 [+?z1<m]dsmxp'
。因此,在处理数据之前,我们不会将所有数字保存在堆栈中,而是逐个读取和处理它们(更准确地说,是逐行读取,因为一行可能包含多个数字)。请注意,空行可以终止输入序列。 - ruvimsed
替换中的空格可以删除,因为dc
不在意参数和操作符之间的空格。(echo "0"; sed 's/$/+/' inputFile; echo 'pq')|dc
- WhiteHotLoveTigerdc -f - -e '[+z1<r]srz1<rp'
比 C 版本慢 250 倍。dc -e '0 0 [+?z1<m]dsmxp'
比 C 版本慢 15 倍。 - undefined纯粹简短的bash。
f=$(cat numbers.txt)
echo $(( ${f//$'\n'/+} ))
f=$(<numbers.txt)
,这是最佳解决方案,因为它不会创建任何子进程。 - loentarf=$(cat); echo $(( ${f//$'\n'/+} ))
放入脚本中,那么您可以将任何内容传输到该脚本或调用它而无需参数进行交互式标准输入(使用Control-D终止)。 - mklement0<numbers.txt
是一种改进,但总的来说,这种解决方案只适用于小型输入文件。例如,对于包含1,000个输入行的文件,在我的机器上,接受的awk
解决方案大约快20倍-并且占用的内存也更少,因为文件不是一次性读取的。” - mklement099999
需要在一台M1 Max和bash 5.2.15
的机器上花费26.7秒,而使用jot
和awk
只需要0.053秒
,另一个awk
生成的结果为0.22秒
。即使将每个整数相加到1亿,也只需要11.5秒,而将所有整数相加到10亿只需要1分55秒。perl
比awk
稍微慢了一点。 - RARE Kpop Manifestoperl -lne '$x += $_; END { print $x; }' < infile.txt
我的想法:
$ cat file.txt | xargs | sed -e 's/\ /+/g' | bc
示例:
$ cat text
1
2
3
3
4
5
6
78
9
0
1
2
3
4
576
7
4444
$ cat text | xargs | sed -e 's/\ /+/g' | bc
5148
grep -v '^$'
。谢谢! - James Oravec