Steve
Steve

Reputation: 54512

awk sum a column and print that sum on each line of input

My file.txt looks like this:

1 12
2 18
3 45
4 5
5 71
6 96
7 13
8 12

I can sum the second column like this:

awk '{ sum += $2 } END { print sum }' file.txt

272

What's the neatest way that I can print that sum on each line? This is what I'm expecting:

1 12 272
2 18 272
3 45 272
4 5 272
5 71 272
6 96 272
7 13 272
8 12 272

Upvotes: 24

Views: 64065

Answers (6)

paxdiablo
paxdiablo

Reputation: 882098

You can use:

awk -v xyzzy=$(awk '{sum+=$2}END{print sum}' file.txt)
    '{print $0" "xyzzy}' file.txt

This unfortunately means going through the information twice but, since you have to do it once before you get the total, there's no real way around it. Any solution will involve storing up the information before outputting anything (whether in arrays, or going back to the file).

The inner awk works out the total and the outer awk assigns that to a variable which can be printed along with each line.

Applying that to the file:

a 1
b 2
c 3
d 4
e 5

gives you, because 1 + 2 + 3 + 4 + 5 is equal to 15:

a 1 15
b 2 15
c 3 15
d 4 15
e 5 15

Upvotes: 7

Taku  Miyakawa
Taku Miyakawa

Reputation: 141

awk, yes, head and paste.

$ yes "`<file.txt awk '{ sum += $2 } END { print sum }'`" | head -n `<file.txt wc -l` | paste -d ' ' file.txt -

Upvotes: 1

Tedee12345
Tedee12345

Reputation: 1362

The ugly solution:

awk '{printf "%s ", $0}{system(" awk \047 {sum+=$2}END{print sum} \047  file ")}' file

Upvotes: 1

kev
kev

Reputation: 161874

Kind of standard awk way.

$ awk 'FNR==NR{sum+=$2;next}; {print $0,sum}' file.txt{,}
1 12 272
2 18 272
3 45 272
4 5 272
5 71 272
6 96 272
7 13 272
8 12 272

Upvotes: 21

Fredrik Pihl
Fredrik Pihl

Reputation: 45670

Use arrays

{ 
    a[NR] = $0
    sum += $2
}
END {
    for (x = 1; x <= NR; x++) {
        print a[x], sum
    }
}

Output

$ awk -f s.awk file.txt 
1 12 272
2 18 272
3 45 272
4 5 272
5 71 272
6 96 272
7 13 272
8 12 272

Read more in Gnu Awk Manual

Upvotes: 3

codaddict
codaddict

Reputation: 455312

Offtopic, but in Perl you can do:

perl -nale '$s+=$F[1];push(@a,$_);END{print $_." $s" for(@a);}' file.txt

Upvotes: 1

Related Questions