Shortest command to calculate the sum of a column of output on Unix?

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

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.


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

I know this question is somewhat dated, but I can't see "my" answer here, so I decided to post nonetheless. I'd go with a combination of

  • tail (to get the lines you need)
  • tr (to shrink down multiple consequitive spaces to one)
  • cut (to get only the needed column)
  • paste (to concatenate each line with a + sign)
  • bc (to do the actual calculation)

ipcs doesn't give an output on my system, so I'll just demo it with 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

I know doing this particular calculation on my system doesn't really make sense, but it shows the concept.

All of the pieces of this solution have been shown in the other answers, but never in that combination.


Python Solution

#!/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

Most Linux distros have Python.

If you want to process stdin as part of a pipline, use

import sys
total = 0
for line in sys.stdin:
   ...etc...

If you want to assume that there's always 3 header lines:

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

One-liner:

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