views:

247

answers:

4

How can I sum (using Linux shell) numbers in a column? If possible, I don't want to use powerful tools like awk or perl. I want something like giveMeNumber | sum

+4  A: 

Since you didn't provide file sample, I'll show the simple (1st column) approach, using Unix's calculator bc and transforming newlines into "+" using tr command - you need an extra 0 at the end since the newline after the last number will create an extra "+" at the very end:

$ cat a
1
2
3
$ cat a | tr "\012" "+" ; echo "0"
1+2+3+0
$ (cat a | tr "\012" "+" ; echo "0") |bc
6

However, I'm not quite sure why you need to avoid Perl, as it's very easy to do as a one-liner:

> perl5.8 -ae '{map {$sum+=$_} <>; print "$sum\n"}' a
6
DVK
http://www.pixelbeat.org/scripts/add
pixelbeat
+1  A: 

Well - if you're using bash (which is probably the most common shell used on Linux, but there isn't actually a single "Linux shell" :-) you could do something like the following:

#!/bin/bash
a=0
while read n; do
  a=$[a+n]
done
echo $a

This would be your sum program - though it's probably a good idea to call it something else since sum is a standard utility for calculating checksums.

psmears
The method you show will work in POSIX shells in addition to Bash. The `$[...]` construct is deprecated, use `$((...))` instead. Or, in Bash, do `(( a += n ))`.
Dennis Williamson
+2  A: 

Why do you want to avoid awk? It's pretty simple to do, and you can easily change which column to sum by changing $1 to $2, $3, etc.

$ seq 10
1
2
3
4
5
6
7
8
9
10
$ seq 10 | awk '{sum += $1} END{print sum}'
55
John Kugelman
+3  A: 
giveMeNumber | (tr '\n' '+'; echo 0) | bc

Assuming that giveMeNumber generates one number per line in the first column, use cut to extract the appropriate column otherwise. The tr command will replace ever newline character with a plus sign:

1
2
3

becomes

1+2+3+

the echo 0 at the end is needed to prevent a parse error from the final + at the end. All of this is fed to bc which sees an arithmetic expression which effectively sums the numbers and prints the result:

$ seq 10|(tr '\n' '+'; echo 0)|bc
55
Robert Gamble