Take the 2-minute tour ×
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.

I understand bash and some other interpreters only perform arithmetic for integers. In the following for loop, how can I accomplish this? I've read that bc can be used but am not sure how to use bc in this situation.

total=0
for number in `cat /path/to/file`; do
        total=$(($total+$number))
done
average=$(($total/10))
echo Average is $average

file:

1.143362
1.193994
1.210489
1.210540
1.227611
1.243496
1.260872
1.276752
1.294121
1.427371
share|improve this question
    
Doesn't make sense to calculate the average in every round of the loop if only the last result is used, does it? –  Hauke Laging May 16 '13 at 13:15
    
ksh (ksh93) and zsh do do floating point arithmetics. –  Stéphane Chazelas May 16 '13 at 14:39
add comment

4 Answers

up vote 10 down vote accepted

You may not want to use bc for this. Perhaps awk would work better:

awk '{sum+=$1};END{print sum/NR}' /path/to/file
share|improve this answer
add comment

As tagged , here is a bash 4.0 alternative to choroba's answer, to avoid wc and sed:

bash-4.2$ mapfile -t a < file

bash-4.2$ (IFS='+'; echo "(${a[*]})/${#a[@]}") | bc -l
1.24886080000000000000
share|improve this answer
    
If it's about bash I think this is much nicer: shopt -s extglob; value=...; value="${value%%*(0)}"; if [ -z "${value##*.}" ]; then value="${value}0"; fi; echo "$value". But for next time: I note your "Organizer" badge... 8-) –  Hauke Laging May 16 '13 at 14:05
    
+1 Clever use of IFS! –  chepner May 16 '13 at 17:36
add comment

I usually use bc for floating point arithmetics:

file=1.txt
echo '('$(<$file)')/'$(wc -l < $file) | sed 's/ /+/g' | bc -l
share|improve this answer
add comment
term=0
file=input
for number in `cat "$file"`; do
        term="${term}+${number}"
done
total="$(echo "$term" | bc -l)"
average="$(echo "${total}/10" | bc -l)"
average="$(echo "$average" | sed -e 's/^\(.*\..*[^0]\)0*/\1/' -e p)"
echo "Total: ${total}"
echo "Average: ${average}"
share|improve this answer
    
Good solution, thanks. –  John B May 16 '13 at 13:42
    
@JohnB Then you should accept it as answer (i.e. click on the green check mark below the voting for my answer). –  Hauke Laging May 16 '13 at 13:48
    
:) I guess it's not hard to tell I'm new to the site...and scripting. –  John B May 16 '13 at 13:53
    
For some reason, using sed in this solution caused $average to echo twice. I substituted with cut -c-9 and it fixed it. Have no clue why. –  John B May 16 '13 at 14:23
    
@JohnB You should really try the awk alternative. Don't use bash for these kind of tasks! –  Bernhard May 16 '13 at 14:58
add comment

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.