22

I run the following command:

grep -o "[0-9] errors" verification_report_3.txt | awk '{print $1}'

and I get the following result:

1
4
0
8

I'd like to add each of the numbers up to a running count variable. Is there a magic one liner someone can help me build?

29
grep -o "[0-9] errors" verification_report_3.txt | awk '{ SUM += $1} END { print SUM }'

That doesn't print the list but does print the sum. If you want both the list and the sum, you can do:

grep -o "[0-9] errors" verification_report_3.txt | awk '{ SUM += $1; print $1} END { print SUM }'
  • Shawn - thank you for your answer. How do I return total back to the bash script out of awk? – Amir Afghani Dec 14 '10 at 21:28
  • 2
    @Amir You would use the first one like this variable=$(grep -o "[0-9] errors" verification_report_3.txt | awk '{ SUM += $1} END { print SUM }') This puts the output of the command (which is only the sum value) into the variable called variable – Shawn J. Goff Dec 14 '10 at 21:33
  • 3
    @Amir Afghani Also, you might want to change your grep to "[0-9]\+ errors". This will match if you have a line reporting >9 errors. – Shawn J. Goff Dec 14 '10 at 21:36
  • Yup, wow I can't believe I missed that. Thank you. – Amir Afghani Dec 14 '10 at 21:43
  • Shawn, the output seems like it's not adding up my results. It looks like this: Total Errors = +259+7581+8852+2014+3189++13572+11438+++6+4172+ – Amir Afghani Dec 14 '10 at 21:58
8

This can all be done in awk as well:

awk '"[0-9]+ errors" {sum += $1}; END {print sum}' verification_report_3.txt
6

You appear to be using GNU system, so if Perl regular expressions support is available, you could write something like this:

grep -Po '[0-9]+(?=\s+errors)' infile | 
  paste -sd+ | 
    bc

P.S. I modified the regular expression (added the + quantifier) to allow numbers > 9.

P.S. Alternatively, awk is sufficient (assuming GNU awk):

awk 'END { print s }
/[0-9]+[[:space:]]+errors/ { 
  s += $1 
  }' infile
  • the first one for me just prints what already went into the pipe... – Xerus May 3 '18 at 19:46
3

Try piping the output from your grep into

awk 'BEGIN {total=0;}{total+=$1;}END {print "Total: ",total}'
2

I use this:

$ echo $(cat file | sed 's/$/+/') 0 | bc

It isn't efficient for large lists, but for most of my use cases it is fine. I usually use a shell function to automate the process so that I only have to provide a file name:

## cheezy summation
##   call from .bashrc
##
getsum () { echo $(cat $1 | sed 's/$/+/') 0 | bc; }
gethsum () { echo $(cat $1 | sed 's/[gG]/*1000M/' | sed 's/[mM]/*1000K/' | sed 's/[kK]/*1000/' | sed 's/$/+/') 0 | bc; }
gethexsum () { echo ibase=16 $(cat $1 | sed 's/$/+/') 0 | bc; }

You can always substitute the end-of-line marker for a specific element separator or character class if your data is delimited in another fashion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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