Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How would you perform addition on the output of every line from awk?

For example

cat foo | awk '{print $1}
42
42
42

I'm looking for the answer to 42+42+42 (126).

I'm trying to write a for loop to do this, but there must be a simpler way

#Not Working, and way too complex
cat foo |awk  '{ print $1 }'|for i in $1 do; foo=$(( foo+$(i) )) done| echo $foo

I could pipe to wc -l but that only prints the number of lines, it does not evaluate them.

How can I evaluate each line from awk?

share|improve this question
    
Do you need to do your addition after awk exits, or can you do the addition within awk? –  glenn jackman Sep 30 '13 at 20:42
    
Both doing the work inside awk or outside of awk would be acceptable. –  spuder Sep 30 '13 at 20:47

4 Answers 4

A basic approach, using your example:

awk '{sum+=$1} END {print sum}' file
share|improve this answer

If you have control over the awk program, do the addition within awk as @jasonwryan shows.

If you really want to sum up the numbers that awk spits out, pipe the output into one of these:

| { tr '\n' '+' ; echo 0; } | bc
| { while read line; do ((sum+=line)); done; echo $sum; }

In the 2nd example, the echo command is within the grouping braces because bash runs the pipeline in a subshell, so changes to the $sum variable will not exist when the subshell exits.

share|improve this answer

Bash can't deal with decimals but it can handle simple manipulation of integers, you just need to use a trick like process substitution to make the variable accessible outside the loop:

n=0;while read i; do let n+=$i; done < <(awk '{print $1}' foo); echo $n;

or

n=0;while read i; do n=$((n+i)); done < <(awk '{print $1}' foo); echo $n;

The n=0 is there just to make sure that $n is always 0, otherwise, running these commands a second time would return 252 instead of 126.


While the most straightforward way would be to use gawk to make the calculation, you could also use a Perl one-liner:

awk '{print $1}' foo | perl -lne '$k+=$_;END{print "$k"};'

The -l flag removes newlines (chomp) and adds one to the end of each printed string, the -n means read the file line by line, saving each line as $_ and run the script provided with -e.

Or do the whole thing in Perl:

perl -alne '$k+=$F[0];END{print "$k"};' foo

The -a flag for Perl turns on automatic line splitting (like gawk). By default, fields are split on spaces but that can be changed using -F. The resulting fields are saved as the @F array so the 1st field is $F[0].

share|improve this answer
    
This is one reason I prefer ksh93 to bash - Korn actually supports floating-point math in the shell. ;) –  dannysauer Oct 6 '13 at 20:11

The one-liner method i usually use for simple totals like this is to pipe to xargs to get all output from awk on one line, then through sed to transform spaces to pluses, and finally into bc to do the calculation:

cat foo | awk '{print $1} | xargs | sed -e 's/ /+/g' | bc
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.