我正在寻找一个命令,它将接受多行文本作为输入,每行包含一个整数,并输出这些整数的总和。
背景说明:我有一个日志文件,其中包括时间测量。通过grep相关行和一些sed
重新格式化,我可以列出该文件中的所有计时。我想计算出总时间。我可以将此中间输出传输到任何命令以进行最终求和。我过去总是使用expr
,但是除非它以RPN模式运行,否则我认为它无法处理这个问题(即使是在RPN模式下也很棘手)。
如何获得整数的总和?
我正在寻找一个命令,它将接受多行文本作为输入,每行包含一个整数,并输出这些整数的总和。
背景说明:我有一个日志文件,其中包括时间测量。通过grep相关行和一些sed
重新格式化,我可以列出该文件中的所有计时。我想计算出总时间。我可以将此中间输出传输到任何命令以进行最终求和。我过去总是使用expr
,但是除非它以RPN模式运行,否则我认为它无法处理这个问题(即使是在RPN模式下也很棘手)。
如何获得整数的总和?
给喜爱Ruby的人
ruby -e "puts ARGF.map(&:to_i).inject(&:+)" numbers.txt
另一种纯Perl的方法,相当易读,不需要任何包或选项:
perl -e "map {$x += $_} <> and print $x" < infile.txt
这里有一个漂亮干净的一行代码,使用的是Raku(之前称为Perl 6):
say [+] slurp.lines
% seq 10 | raku -e "say [+] slurp.lines"
55
slurp
默认从标准输入读取;它返回一个字符串。在字符串上调用lines
方法,将返回该字符串的逐行列表。+
将其转换为约简元操作符,这个元操作符将列表“约简”为单个值:列表中各值的总和。say
函数然后将其带有换行符的输出打印到标准输出流。% echo "1\n2\nnot a number" | raku -e "say [+] slurp.lines"
Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏not a number' (indicated by ⏏)
in block <unit> at -e line 1
lines
没有任何参数时与slurp
的语义相同,但它生成一个Str
序列,而不是单个Str
。 - Elizabeth Mattijsenawk 'BEGIN {sum=0} \
{sum=sum + $2} \
END {print "tot:", sum}' Yourinputfile.txt
如果你感觉熟悉的话,你可以用Python来完成:
以下内容未经测试,仅供参考:
out = open("filename").read();
lines = out.split('\n')
ints = map(int, lines)
s = sum(ints)
print s
Sebastian指出了一行脚本:
cat filename | python -c"from fileinput import input; print sum(map(int, input()))"
cat
的作用是展示脚本既适用于标准输入,也适用于在argv[]中的文件(就像Perl中的 while(<>)
)。如果你的输入是来自于一个文件,那么 '<' 就不必要了。 - jfs<numbers.txt
演示了它可以像 cat numbers.txt |
一样在标准输入上正常工作。而且它不会教授不良习惯。 - Xiong Chiamiovcommand < file
本身就是一个不好的习惯。应该使用 < file command
。Bash 的单行命令应该易于从输入到输出从左到右阅读。 - Marcel BesixdouzeC语言(非简化版)
seq 1 10 | tcc -run <(cat << EOF
#include <stdio.h>
int main(int argc, char** argv) {
int sum = 0;
int i = 0;
while(scanf("%d", &i) == 1) {
sum = sum + i;
}
printf("%d\n", sum);
return 0;
}
EOF)
int
应该改为 long
。在 EOF
和 )
之间应该有一个换行符。 - undefinedRacket中的一行代码:
racket -e '(define (g) (define i (read)) (if (eof-object? i) empty (cons i (g)))) (foldr + 0 (g))' < numlist.txt
$ cat n 2 4 2 7 8 9
$ perl -MList::Util -le 'print List::Util::sum(<>)' < n
32
$ perl -MList::Util -le 'print List::Util::sum(<>)'
1
3
5
^D
9
然而,这个方法会将文件全部读入内存,因此不适合处理大文件。可以参考j_random_hacker的回答,他提供了一种避免读入整个文件的解决方案。
My version:
seq -5 10 | xargs printf "- - %s" | xargs | bc
seq -s+ -5 10 | bc
- agc提前道歉,由于反引号(“`”)的可读性较差,但在除bash外的其他shell中起作用,因此更易于复制粘贴。如果您使用接受它的shell,则$(command ...)格式比 `command ...` 更易读(也更易于调试),因此请随意修改以保持理智。
我在我的bashrc中有一个简单的函数,将使用awk计算多个简单的数学问题。
calc(){
awk 'BEGIN{print '"$@"' }'
}
这将包括使用加、减、乘、除、幂、余数、平方根、正弦、余弦和括号等操作符(具体取决于您所使用的 awk 版本)......您甚至可以使用 printf 函数使浮点数输出更为精确,但我通常只需要这些。
对于这个特定问题,我会针对每行执行以下操作:
calc `echo "$@"|tr " " "+"`
因此,用于对每行求和的代码块应该如下所示:
while read LINE || [ "$LINE" ]; do
calc `echo "$LINE"|tr " " "+"` #you may want to filter out some lines with a case statement here
done
如果您只想逐行对它们求和,那么这就是一个方法。但是如果要对数据文件中的每个数字进行总计,则需要另一种方法。
VARS=`<datafile`
calc `echo ${VARS// /+}`
顺便说一句,如果我需要快速在桌面上做些什么,我会使用这个:
xcalc() {
A=`calc "$@"`
A=`Xdialog --stdout --inputbox "Simple calculator" 0 0 $A`
[ $A ] && xcalc $A
}
$()
的古老 shell?我需要翻译这句话。 - alexia