Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Unix上计算一列输出总和的最短命令?_Unix_Math_Shell_Ksh - Fatal编程技术网

在Unix上计算一列输出总和的最短命令?

在Unix上计算一列输出总和的最短命令?,unix,math,shell,ksh,Unix,Math,Shell,Ksh,我确信在Unix系统上有一种快速简便的方法来计算一列值的总和(可能使用awk或xargs之类的方法),但是现在唯一想到的是编写一个shell脚本来逐行解析行 例如,修改下面的命令以计算和显示SEGSZ列(70300)的总数的最简单方法是什么 您可以首先通过cut运行数据,这至少会减少列 然后,您应该能够将其导入grep,去掉非数字 然后。。。嗯,那我就不确定了。可以通过管道将其传输到bc。如果没有,它当然可以交给shell脚本来添加每个项目 如果您使用tr将换行符(\n)更改为空格(),并通过x

我确信在Unix系统上有一种快速简便的方法来计算一列值的总和(可能使用
awk
xargs
之类的方法),但是现在唯一想到的是编写一个shell脚本来逐行解析行

例如,修改下面的命令以计算和显示SEGSZ列(70300)的总数的最简单方法是什么


您可以首先通过
cut
运行数据,这至少会减少列

然后,您应该能够将其导入
grep
,去掉非数字

然后。。。嗯,那我就不确定了。可以通过管道将其传输到
bc
。如果没有,它当然可以交给shell脚本来添加每个项目

如果您使用
tr
将换行符(
\n
)更改为空格(
),并通过xargs将其传输到脚本中,该脚本将循环直到不再有输入,然后添加每一个输入,您可能会得到答案

因此,类似于以下内容:

cat <whatever> | cut -d'\t` -f7 | grep -v <appropriate-character-class> | tr '\n' ' ' | xargs script-that-adds-arguments
添加参数的cat | cut-d'\t`-f7 | grep-v | tr'\n''xargs脚本 我的
cut
标记可能有点错误-但是
man
是你的朋友:)

或者没有尾巴:

ipcs -mb | awk 'NR > 3 { sum += $7 } END { print sum }'
将awk与bc一起使用可产生任意长结果(归功于Jouni K.):

Python解决方案

#!/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作为管道的一部分进行处理,请使用

import sys
total = 0
for line in sys.stdin:
   ...etc...
如果要假设始终有3个标题行:

import sys
total = 0
for line in sys.stdin.readlines()[3:]:
    total += int(line.split()[6])
print total
一艘班轮:

import sys; print sum( [int(line.split()[6]) for line in sys.stdin.splitlines()[3:]] )

您可以在任何在线awk参考中查找:

ipcs | awk '
BEGIN { sum = 0 }
/0x000000/ { sum = sum + $2 }
END {print sum}'

我有一个实用程序脚本,它可以简单地将所有列相加。通常很容易从单行输出中获取所需的内容。作为奖励,可以识别一些SI后缀

#!/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 "";
}

感谢上面的Python一行!。它帮助我轻松检查驱动器上的已用空间。 这里是一个混合的shell/Python一行程序,用于计算设备/dev/sda上的已用空间(以兆字节为单位)。我花了一些时间才发现,所以,也许有人也觉得这很有用

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/更少shell:

 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])"

再次感谢

我将尝试构造一个计算字符串并按如下方式将其馈送给bc:

  • grep包含数字的行
  • 删除每行数字前后的所有字符
  • xargs结果(获取由空格分隔的数字字符串)
  • 将空格转换为“+”字符
  • 好胃口
    ipcs-mb | grep-w'^m'| sed's/^..*\s/'| xargs | tr'+| 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'+))

    双括号前后的间距是可选的。

    我知道这个问题有点过时,但我在这里看不到“我的”答案,所以我还是决定发布。我会选择一个组合

    • 尾部(以获取所需的线条)
    • tr(将多个约束空间缩小为一个)
    • 剪切(仅获取所需的列)
    • 粘贴(用
      +
      符号连接每一行)
    • bc(进行实际计算)
    ipcs
    在我的系统上没有输出,所以我将用
    df
    演示它:

    # 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
    
    我知道在我的系统上进行这种特殊的计算是没有意义的,但它展示了这个概念


    此解决方案的所有部分已在其他答案中显示,但从未在该组合中显示。

    要对列中的值求和,可以使用GNU datamash。由于前四行不包含要求和的值,因此我们使用
    tail+4
    删除它们

    ipcs -mb  | tail +4 | datamash -W sum 7
    

    -W
    选项将字段分隔符设置为(可能有多个)空白。

    如果您有特定的、多个要求和的列,可以使用:

    input_command | awk '{s1+=$1;s2+=$2;s3+=$3;s4+=$4;s5+=$5}END{print s1,s2,s3,s4,s5}'
    

    如果您想对第1-5列求和,这将起作用。

    不可思议的是,perl没有被示例化

    有关-a(表示-n),请参见
    perldoc perlrun
    。 和
    perldoc perlvar
    了解美元。还有朋友

    $ df |perl -aE'$.<2or$u+=$F[2]}{say"Used: $u"'
    Used: 129016836
    
    $df | perl-aE'$.1,k=>1e3,k=>2**10,M=>2**20,G=>2**30,T=>2**40);%D=反向%M}
    印刷品;
    
    如果($.0和do{$V[$\u]+=$w;$\u谢谢,非常有用!运行该命令,我得到的结果是:6.59246e+08。有没有办法强制awk显示准确的值(而不是科学符号)?Andrew,awk有一个printf函数:printf“%d\n”,sum应该这样做。(我猜不是%f。不知道为什么我认为它是浮点:p)另外,如果您知道它总是最后一个字段,但不想计算字段数(或者如果字段数不同),您可以使用print$NF。这很令人不安!但非常酷…我[几乎]想取消我的提议:D#用法:$0[文件…]
    # 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
    
    ipcs -mb  | tail +4 | datamash -W sum 7
    
    input_command | awk '{s1+=$1;s2+=$2;s3+=$3;s4+=$4;s5+=$5}END{print s1,s2,s3,s4,s5}'
    
    $ df |perl -aE'$.<2or$u+=$F[2]}{say"Used: $u"'
    Used: 129016836
    
    $ df -h |perl -anE'$|=1;
      BEGIN{%M=(""=>1,k=>1e3,K=>2**10,M=>2**20,G=>2**30,T=>2**40);%D=reverse%M}
      print;
      if($.<2){@V=map length(),/\s*+[^a-z]\S*(?:\s+[a-z]+)*/g;next} # parse header
      ($w=($_==$#V)+length($F[$_])-$V[$_])>0 and do{$V[$_]+=$w;$_<$#V and $V[$_+1]-=$w} for 0..$#F; # optimize column widths
      $S[$_]+=($F[$_]=~/^(\d+(?:[.]\d*)?)([kKMGT])?$/aa?$1*$M{($D||=$2)&&$2}:-Inf)for 0..$#F; # scale numeric values
    }{ # show results
      say join("",map+("-"x($V[$_]-1)).($S[$_]<0?"^":"+"),0..$#V);
      $V[$_]+=$V[$_-1]for 1..$#V;
      if($D){for$s(@S){@s=sort{$b<=>$a}grep{$_<$s}keys%D and$s=sprintf"%.1f%s",$s/$s[0],$D{$s[0]}}}
      say sprintf+("%s%*s"x@S),map{((!$p||($_>0 and length($S[$_])>=($w=($V[$_]-$V[$_-1])))?(($q?"\n":(($p=$q=1)&&"")),$V[$_]):("",0+$w)),$S[$_])}grep{$S[$_]!=-Inf}0..$#S;
    '