To calculate average by taking command line argument

The task is that if input numbers:

``````4
1
2
9
8
``````

Output=(sum of all except first_number_in_series)/first_number in series Then output average should be `1+2+9+8/(first_number_in series)=20/4=5`

I have tried the following code, however not able to achieve the task. I will be grateful if anyone can point out the mistake.

``````#!/bin/bash
sum=0
count=1
for x in \$*
do
if [ \$count -eq 1 ]
then
p=\$x
else
sum=\$((\$sum + \$x))
fi
((count++))
done
echo "scale=3;\$sum/\$p" | bc
``````
• What's wrong with your code? – GingerPlusPlus Feb 7 '16 at 18:56
• not giving the desired output...pls check – frp farhan Feb 7 '16 at 18:58
• For me, it looks like you include first number in your average, and it's the main problem. I'm going to check if I'm right. – GingerPlusPlus Feb 7 '16 at 18:59
• I think the problem may be elsewhere; your script does what you want, but maybe you're calling it differently? It's expecting the numbers to be passed to it while your answer below specifically reads from stdin and ignores any numbers passed to it. Show us the error you're getting. – Jeff Schaller Feb 7 '16 at 19:51
• Feels like it would be easier to `shift` p off before starting to do the sum. – azzid Feb 7 '16 at 19:57

You failed to say that the numbers are given to the script in the stdin.

For that, this code will work:

``````#!/bin/bash
count="\${x[0]}" ; unset x[0]
for y in \${x[@]}; do (( sum+=y )); done
a="\$(echo "scale=8; \$sum/\$count" | bc)"
LC_ALL=C printf '%0.3f\n' "\$a"
``````

Test it as this:

``````\$ printf '%s\n' 4 1 2 9 8 | ./script
5.000
\$ printf '%s\n' 6 1 2 9 8 13 25 | ./script
9.667
``````
• What is the difference between stdin and normal inputs?? I am new to bash, it will be greatful if u can clearify this for me...thnx – frp farhan Feb 8 '16 at 3:37
• Also, in the above code if the output is 9.6666, then answer is expected to be 9.667,then how to achieve this task in ur testcase 2 wherein the answer is 9.6666 how to display rounded off value such as 9.667? – frp farhan Feb 8 '16 at 3:40
• The difference is like the difference between this two lines: `./script 1 2 3 4` and `echo 1 2 3 4 | ./script`. The first supply the arguments in the array of "positional arguments" (similar to c ARGV[]), the second supply the values in the stdin input (no ARGV is set). – user79743 Feb 8 '16 at 4:42
• Rounding is a very slippery slope. You can get what you ask for with printf: `LC_ALL=C; a=9.666666; printf '%0.3f' "\$a"` (output 9.667), but even that is bound to fail in some other corner cases. – user79743 Feb 8 '16 at 4:48
• In which cases will it result into failure??? and in our code, where shall i include printf '%0.3f'?? – frp farhan Feb 8 '16 at 5:32

Since you need floating point calculation, you will end up using bc, or awk, anyways. Why not use Awk to solve the whole problem? Here is a Awk only solution, I used n for numerator and d for denominator:

``````\$ printf "4\n1\n2\n9\n8\n" | awk '{if (NR == 1) {d = \$0}; if (NR != 1) {n += \$0}} END{printf "%.03f\n", n/(d*1.0)}'
5.000
``````

You were including the first number in the sum and you wrote a bad condition:

`if [ count -eq "1" ]`

`if [ \$count -eq 1 ]`

`\$` operator let you access to a variable and you were using 1 as a String instead of a integer.

``````#!/bin/bash
p=\$n
sum=0
count=1
while [ \$count -le \$p ]
do