Tak
Tak

Reputation: 11704

Doing math on the linux command line

I have a log file from a web server which looks like this;

1908 462
232 538
232 520
232 517

My task is to total column 1 and column 2 in a bash script. My desired output is;

2604 2037

I know of awk or sed which could go a long way to solving my problem but I can't fathom how to actually do it. I've trawled examples on Google but haven't turned up anything useful. Can someone point me in the right direction please?

Upvotes: 0

Views: 1510

Answers (4)

potong
potong

Reputation: 58371

These might work for you:

sed ':a;N;s/ \(\S*\)\n\(\S*\) /+\2 \1+/;$!ba;s/ /\n/p;d' file | bc | paste -sd' '

or

echo $(cut -d' ' -f1 file | paste -sd+ | bc) $(cut -d' ' -f2 file| paste -sd+ |bc)

Upvotes: 0

Can Kavaklıoğlu
Can Kavaklıoğlu

Reputation: 507

Here is a non-awk alternative for you:

echo $( cut -f 1 -d " " log_file | tr '\n' + | xargs -I '{}' echo '{}'0 | bc ) $( cut -f 2 -d " " log_file | tr '\n' + | xargs -I '{}' echo '{}'0 | bc )

Make sure you replace log_file with your own file and that file does not have any extra or unnecessary new lines. If you have such lines then we would need to filter those out using a command like the following:

grep -v "^\s*$" log_file

Upvotes: 0

Keith Thompson
Keith Thompson

Reputation: 263197

awk '{a += $1; b += $2} END { print a " " b }' foo.log

(Note the complete lack of error checking.)

EDIT :

Ok, here's a version with error checking:

awk 'BEGIN { ok = 1 } { if (/^ *[0-9]+ +[0-9]+ *$/) { a += $1; b += $2 } else { ok = 0; exit 1 } } END { if (ok) print a, b }' foo.log

If you don't want to accept leading or trailing blanks, delete the two " *"s in the if statement.

But this is big enough that it probably shouldn't be a one-liner:

#!/usr/bin/awk -f

BEGIN {
    ok = 1
}

{
    if (/^ *[0-9]+ +[0-9]+ *$/) {
        a += $1
        b += $2
    }
    else {
        ok = 0
        exit 1
    }
}

END {
    if (ok) print a, b
}

There's still no overflow or underflow checking, and it assumes that there will be no signs. The latter is easy enough to fix; the former would be more difficult. (Note that awk uses floating-point internally; if the sum is big enough, it could quietly lose precision.)

Upvotes: 6

user353608
user353608

Reputation:

Try

awk '{a+=$1;b+=$2} END {print a, b}' file

Upvotes: 3

Related Questions