I have a file with multiple tags with a number next to it e.g.

other <tags> and data
other <tags> and data

How would I search through the file and count up all the numbers next to the overall tag? and then divide the number by the number of overall tags, to get an overall average.

So for example in the code above the average would be 3.

And then loop through all the files in the current directory and list the overall average for each file.

  • If any of the existing answers solves your problem, please consider accepting it via the checkmark. Thank you! – Jeff Schaller Apr 25 '17 at 10:37

Using awk (assuming all that is on overall lines is that and a number)

awk 'x+=sub(/<Overall>/,""){y+=$0}END{print "AVG:",y/x}' file

x is incremented for every successful sub of <Overall> with nothing. This means that it is only incremented on lines that contain <Overall>.

The block after then adds the number that is left on the line to the total.

END executes at the end of the program.

In the end block the avg is printed.

EDIT:for lots of files

awk 'x+=sub(/<Overall>/,""){y+=$0}END{print FILENAME,"AVG:",y/x}' LISTOFFILES
  • Would I be able to put this code inside a for loop and print out the average of every file in the directory? – tom Feb 15 '16 at 14:12
  • @tom Editted, please put all the information in your question in the future though please. – 123 Feb 15 '16 at 14:17

With perl:

perl -lne 'for (/<Overall>([\d.eE+-]+)/g) {$n++; $sum += $1}
           END{print $sum/$n if $n}'

That has the benefit of being able to handle more than one <Overall> tag per line. [\d.eE+-]+ is a crude matcher for a floating point decimal number (allowing things like 12, 1.2, -1E+20 (though also things that are not valid numbers)).

  • why use -l flag ? – 123 Feb 15 '16 at 14:21
  • @123 for the output to be on a line. – Stéphane Chazelas Feb 15 '16 at 14:28

Here's a crude way in awk:

awk '/^<Overall>/ { 
    sub("<Overall>", ""); 
    sum += $1; 
  END { print sum / lines}' 
  tags  ### this is your input file
  • gsub seems a bit redundant if only one occurs per line. – 123 Feb 15 '16 at 14:03
  • 1
    good point, I'll update accordingly – Jeff Schaller Feb 15 '16 at 14:20

Here's a solution using a few nifty utilities:

grep "^<Overall>\d\+" file | cut -c 10 | paste -s -d + - | bc
  1. Search through the file for lines beginning with "<Overkill>" followed by a string of digits (i.e. a number).
  2. Cut out the number from the rest of the line.
  3. Concatenate all the lines with a "+" symbol in between
  4. Pass the result to bc, which will compute the sum

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.