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.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

<Overall>4
other <tags> and data
<Overall>2
other <tags> and data
<Overall>3

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.

share|improve this question

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
share|improve this answer
    
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 at 14:12
    
@tom Editted, please put all the information in your question in the future though please. – 123 Feb 15 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)).

share|improve this answer
    
why use -l flag ? – 123 Feb 15 at 14:21
    
@123 for the output to be on a line. – Stéphane Chazelas Feb 15 at 14:28

Here's a crude way in awk:

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