0

I have input files of this format

real 0.00  
user 0.00  
sys 0.00  
real 0.00  
user 0.00  
sys 0.00  
real 0.00  
user 0.00  
sys 0.00  

I'm writing a bash script to get the average of the 'real' values. This is the script I've written

#! /bin/sh

# FILES=/home/myfiles

 for f in $FILES
 do
        echo " Processing $f file.."
        sum=0;
        grep real $f  | while read LINE; do
                value=$(sed "s/[^0-9]//g")
                #value=`awk "^[0-9]"`
                echo $value
                $sum+=$value
        done
        #average=$sum/10;
        #echo $average
 done

But I'm getting an error in this stmt

$sum+=$value

Any solutions plz ?

1
  • Are you sure, time will always display two decimal places? Commented Apr 1, 2011 at 23:20

4 Answers 4

2

Use this:

sum+=$value

Otherwise you'd be saying "0+=$value"

Also, you can do:

grep real $f  | while read LINE value; do

That'll avoid the need to sed/awk.

Sign up to request clarification or add additional context in comments.

5 Comments

thanks, I tried this its wrking, But the value of sum is being appended like a string instead of adding like an integer sum: 0.000.000.000.000.000.000.00
@Erik, in the end, awk or bc is still needed to do decimal calculations. In the end, its still better to use just awk to do the average.
bash will work fine, you just need to strip the decimal point (and add it back to your result) ... once you are dealing with just ints - try to perform the operation with let sum+=value or ((sum+=value))
@jessi ... did you get the part about removing the decimal point?
@jessi - I think I know why it didnt work ... please see full answer below
2

bash does not support floating point arithmetic. It only supports integer. If you don't care how to get the result, awk is better equipped for this:

awk '/real/ {sum += $2} END {print sum}' files*

The /real/ says, "look for those lines with the word real", then {sum += $2} means add the second field to sum. By default, a variable like sum will starts as empty or zero depends on context. Finally, the END pattern says, "after processing all the files, print the sum."

Comments

2

Its better to use awk or some programming language that does file processing as well as floating maths all in one. Bash does not support floating point maths. The problem with your script is , you call external sed command for every "real" lines you find. This is a performance hit.

awk '/real/{s+=$2;c++}END{print "average is: " s/c}' file

Comments

0

Here is a quick try, based on our discussion above. I tried not to change your script too much here is a summary

  • Values are dumped into an array (the pipes you had cause the math to occur at a subshell, results would not make it up to the 'main' shell
  • Added more processing in the sed expression to strip leading zeros (but make sure there is at least one digit)
  • I didnt follow why to calculate average you divided by 10, so I use the actual count of items in the array
  • finally, assuming you want the average in the same unit of meeasurement as the input - I am printing with printf the result of dividing by 100.

-

#! /bin/sh

# FILES=/home/myfiles
FILES=a
 for f in $FILES
 do
        echo " Processing $f file.."
        values=($(grep real ${f} | sed -e "s/[^0-9]//g" -e "s/^0*//" -e "s/^$/0/"))
        sum=0;
        for value in ${values[@]}; do
          echo $value
          ((sum+=value))
        done
        average=$((sum/${#values[@]}));
        printf "AVG: %d.%02d\n" $((average/100)) $((average%100))
 done

1 Comment

@jessi You are welcome! (please remember to accept an answer, using the check-mark under the number on the left)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.