Shortest command to calculate the sum of a column

2019-03-08 02:52发布

I'm sure there is a quick and easy way to calculate the sum of a column of values on Unix systems (using something like awk or xargs perhaps), but writing a shell script to parse the rows line by line is the only thing that comes to mind at the moment.

For example, what's the simplest way to modify the command below to compute and display the total for the SEGSZ column (70300)?

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

10条回答
男人必须洒脱
2楼-- · 2019-03-08 03:33

You could look it up in any online awk reference:

ipcs | awk '
BEGIN { sum = 0 }
/0x000000/ { sum = sum + $2 }
END {print sum}'
查看更多
该账号已被封号
3楼-- · 2019-03-08 03:34
ipcs -mb | tail +4 | awk '{ sum += $7 } END { print sum }'

Or without tail:

ipcs -mb | awk 'NR > 3 { sum += $7 } END { print sum }'

Using awk with bc to have arbitrary long results (credits to Jouni K.):

ipcs -mb | awk 'NR > 3 { print $7 }' | paste -sd+ | bc
查看更多
仙女界的扛把子
4楼-- · 2019-03-08 03:34

I have a utility script which simply adds up all columns. It's usually easy enough to grab the one you want from the one-line output. As a bonus, some SI-suffixes are recognized.

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

Example with custom field separator:

$ head /etc/passwd | addcol -F:
0 0 45 39 0 0 0
查看更多
一纸荒年 Trace。
5楼-- · 2019-03-08 03:35

If you have specific, multiple columns you want to sum, you can use:

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

which will work if you want to sum columns 1–5.

查看更多
手持菜刀,她持情操
6楼-- · 2019-03-08 03:36

You could start by running the data through cut - which would at least trim the columns down.

You should then be able to pipe that into grep, stripping-out non-numerics.

Then ... well, then I'm not sure. It might be possible to pipe that to bc. If not, it could certainly be handed to a shell script to add each item.

If you used tr to change the newlines (\n) to spaces (), and piped that through xargs into your script that loops until there are no more inputs, adding each one, you may have an answer.

So, something akin to the following:

cat <whatever> | cut -d'\t` -f7 | grep -v <appropriate-character-class> | tr '\n' ' ' | xargs script-that-adds-arguments

I may have the cut flags slightly wrong - but man is your friend :)

查看更多
干净又极端
7楼-- · 2019-03-08 03:43

I would try to construct a calculation string and feed it to bc as follows:

  1. grep the lines that contain the numbers
  2. sed away all characters before (and after) the number on each line
  3. xargs the result (to get a string of numbers separated by blanks)
  4. tr anslate the blanks to '+' characters
  5. good appetite bc!

ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' + | bc

Looks like this is slightly longer than the awk solution, but for everyone who can't read (and understand) the odd awk code this may be easier to grasp... :-)

If bc is not installed you can use double parentheses in step 5 above to calculate the result:

  • echo $(( $(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) )) or
  • SUM=$(( $(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) )) or
  • (( SUM=$(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) ))

The spacing after and before the double parentheses is optional.

查看更多
登录 后发表回答