Shortest command to calculate the sum of a column of output on Unix?
我相信有一种快速而简单的方法可以计算Unix系统上一列值的总和(可能使用
例如,修改下面的命令以计算和显示SEGSZ列(70300)的总数的最简单方法是什么?
1 2 3 4 5 6 7 | ipcs -mb | head -6 IPC status from /dev/kmem as of Mon Nov 17 08:58:17 2008 T ID KEY MODE OWNER GROUP SEGSZ Shared Memory: m 0 0x411c322e --rw-rw-rw- root root 348 m 1 0x4e0c0002 --rw-rw-rw- root root 61760 m 2 0x412013f5 --rw-rw-rw- root root 8192 |
1 | ipcs -mb | tail +4 | awk '{ sum += $7 } END { print sum }' |
或无尾:
1 | ipcs -mb | awk 'NR > 3 { sum += $7 } END { print sum }' |
使用带BC的awk获得任意长结果(归功于
1 | ipcs -mb | awk 'NR > 3 { print $7 }' | paste -sd+ | bc |
我将尝试构造一个计算字符串,并将其馈送给BC,如下所示:
看起来这比awk解决方案稍微长一点,但是对于每个不能阅读(和理解)奇怪的awk代码的人来说,这可能更容易理解…-)
如果没有安装BC,可以使用上面步骤5中的双括号来计算结果:
echo $(( $(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) )) 或SUM=$(( $(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) )) 或(( SUM=$(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) ))
双括号前后的间距是可选的。
我有一个实用程序脚本,它简单地将所有列相加。它通常很容易从单行输出中获取所需的数据。作为奖励,一些SI后缀被识别。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/usr/bin/awk -f # Sum up numerical values by column (white-space separated) # # Usage: $0 [file ...] # # stern, 1999-2005 { for(i = 1; i <= NF; ++i) { scale = 1 if ($i ~ /[kK]$/) { scale = 1000 } if ($i ~ /[mM]$/) { scale = 1000*1000 } if ($i ~ /[gG]$/) { scale = 1000*1000*1000 } col[i] += scale * $i; } if (NF > maxnf) maxnf = NF; } END { for(i = 1; i <= maxnf; ++i) { printf" %.10g", col[i] } print""; } |
自定义字段分隔符示例:
1 2 | $ head /etc/passwd | addcol -F: 0 0 45 39 0 0 0 |
我知道这个问题有点过时,但我在这里看不到"我的"答案,所以我还是决定发布。我想结合
- 尾巴(为了得到你需要的线条)
- tr(将多个互易空间缩小为一个)
- 剪切(仅获取所需列)
- 粘贴(用
+ 符号连接每一行) - BC(做实际计算)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 33027952 4037420 27312812 13% / udev 10240 0 10240 0% /dev tmpfs 102108 108 102000 1% /run /dev/xvda1 33027952 4037420 27312812 13% / tmpfs 5120 0 5120 0% /run/lock tmpfs 204200 0 204200 0% /run/shm /dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web1/log /dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web2/log /dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web3/log /dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web4/log /dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client2/web5/log /dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client2/web6/log # df | tail -n +2 | tr -s ' ' | cut -d ' ' -f 2 | paste -s -d+ | bc 264545284 |
我知道在我的系统上做这个特别的计算是没有意义的,但是它显示了这个概念。
此解决方案的所有部分都已在其他答案中显示,但从未在该组合中显示。
Python溶液
1 2 3 4 5 6 7 8 9 10 | #!/usr/bin/env python text= file("the_file","r") total= 0 for line in text: data = line.split() if data[0] in ('T', 'Shared', 'IPC'): continue print line segsize= int(data[6]) total += segsize print total |
大多数Linux发行版都有python。
如果要将stdin作为pipline的一部分进行处理,请使用
1 2 3 4 | import sys total = 0 for line in sys.stdin: ...etc... |
如果您想假设始终有3个标题行:
1 2 3 4 5 | import sys total = 0 for line in sys.stdin.readlines()[3:]: total += int(line.split()[6]) print total |
一班轮:
1 | import sys; print sum( [int(line.split()[6]) for line in sys.stdin.splitlines()[3:]] ) |
您可以在任何在线awk参考中查找它:
1 2 3 4 | ipcs | awk ' BEGIN { sum = 0 } /0x000000/ { sum = sum + $2 } END {print sum}' |
您可以首先通过
然后您应该能够将其导入
然后…好吧,那我不确定。可能可以通过管道将其输送到
如果使用
因此,类似于以下内容:
1 2 | cat <whatever> | cut -d'\t` -f7 | grep -v | tr ' ' ' ' | xargs script-that-adds-arguments |
我可能把
如果要求和的列是特定的多列,则可以使用:
1 | input_command | awk '{s1+=$1;s2+=$2;s3+=$3;s4+=$4;s5+=$5}END{print s1,s2,s3,s4,s5}' |
如果您想对第1-5列求和,这将起作用。
要对列中的值求和,可以使用gnu datamash。由于前四行不包含要求和的值,因此我们使用
1 | ipcs -mb | tail +4 | datamash -W sum 7 |
感谢上面的python一行程序!它帮助我轻松检查我的驱动器上的已用空间。这里有一个混合的shell/python一行程序,它可以计算设备/dev/sda上的已用空间(兆字节)。我花了一段时间才发现,所以,也许有人也觉得这很有用。
1 | df -h -B 1M | grep dev/sda | tr -s ' '| cut -d' ' -f3 |python -c"import sys; print sum([int(num) for num in sys.stdin.readlines()])" |
或更多python/less shell:
1 | df -h -B 1M | python -c"import sys; print sum([int(l.split()[2]) for l in sys.stdin.readlines() if '/dev/sda' in l])" |
再次感谢!