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
-
"How do I get a nail into a piece of wood? I don't want to use a hammer." Why on earth would you want to avoid the tools that are perfect for the job? – William Pursell May 24 '10 at 16:08
-
Possible dupe: http://stackoverflow.com/questions/2702564/how-can-i-quickly-sum-all-numbers-in-a-file/2702614#2702614 – brian d foy May 24 '10 at 16:33
-
@William: Don't kill a flea with a sledgehammer – yassin May 24 '10 at 16:56
-
3@William: Why would you assume that the asker's environment is the same as yours? There are plenty of embedded platforms that don't provide Perl or AWK, or that use cut-down variants (a la BusyBox) that lack the needed functionality. Or, he might be writing a single script that needs to run on multiple hosts/distros with different (and incompatible) Perl/AWK installations. Point is, IT HAPPENS. I don't think your lack of wisdom/foresight excuses your rudeness. – Ryan B. Lynch Jul 30 '10 at 16:51
-
@Ryan: Because he said "using linux shell". If there is a reason to avoid perl and awk, that's one thing. "I don't want to use powerful tools" is not a reason. – William Pursell Jul 31 '10 at 02:18
-
@William: I was asking for something short, a single command that does the job, something like seq 10 | sumNums. I already know how to do it using AWK, Perl or anything else. – yassin Jul 31 '10 at 10:31
-
2@William: You think it's OK to mock and deride, if askers don't explain themselves to your satisfaction? I can't agree. And are you sure you weren't just mocking him, trying to demonstrate your own superiority? If you really did want to clarify his rationale, you could have just been polite about it, and instead you chose to be rude. – Ryan B. Lynch Aug 03 '10 at 18:47
-
I've re-read my comment now with 2.5 months of perspective, and I really fail to see how my comment is either mocking, derisive, or rude. I believe the OP is explicitly avoiding tools that are ideal for what he wants to accomplish. I am trying to demonstrate with an illustration that unless he has very good reasons for avoiding those tools, he should not do so. – William Pursell Aug 04 '10 at 05:27
5 Answers
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

- 126,886
- 32
- 213
- 327
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

- 106,424
- 25
- 145
- 137
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

- 349,597
- 67
- 533
- 578
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.

- 26,070
- 4
- 40
- 48
-
1The 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 May 24 '10 at 15:12