Bash - Calculate the Average of Numbers Inputted
Still not sure what you want a to be. But I think you can just loop 3 times. Then each iteration get a set of numbers, and add them up and keep track of how many you have. So something like below. (note $numbers and $sum are initialized to 0 automatically)
#!/bin/bash
sum=0
numbers=0
for a in {1..3}; do
read -p $'Enter a set of numbers:\n' b
for j in $b; do
[[ $j =~ ^[0-9]+$ ]] || { echo "$j is not a number" >&2 && exit 1; }
((numbers+=1)) && ((sum+=j))
done
done
((numbers==0)) && avg=0 || avg=$(echo "$sum / $numbers" | bc -l)
echo "Sum of inputs = $sum"
echo "Number of inputs = $numbers"
printf "Average input = %.2f\n" $avg
Where example output would be
Enter a set of numbers:
1 2 3
Enter a set of numbers:
1 2 3
Enter a set of numbers:
7
Sum of inputs = 19
Number of inputs = 7
Average input = 2.71
A simple small shell script to compute averages
the code below works, you can probably optimize it if you want (or use awk, perl, etc):
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: \"$0\" <filename>"
exit
fi
if [ ! -f $1 ]; then
echo "$1 file not found."
echo "Usage: $0 <filename>"
exit
fi
sum=0
count=0
arq=$1
while read line
do
num=`echo ${line#* }`
sum=`expr $sum + $num`
count=`expr $count + 1`
done < "$arq"
if [ "$count" != 0 ]
then
avg=`expr $sum / $count`
printf "Sum= \"$sum\" \n Count= \"$count\" \n Avg= \"$avg\""
exit 0
else
printf "Sum= \"$sum\" \n Count= \"$count\" \n Avg= undefined"
exit 0
fi
Calculate the Average of Numbers from command output
nvidia-smi --format=csv --query-gpu=utilization.gpu | awk '/[[:digit:]]+[[:space:]]%/ { tot+=$1;cnt++ } END { print tot/cnt }'
Pipe the output of nvidia-smi ... to awk. Process lines that have a one or more digits, a space and then a "%". Create a running total (tot) and also, count the number of occurrences (cnt) At the end, divide tot by cnt and print the result.
Bash script to calculate average mark
In case you are ok with awk
(where we need not to use so many commands in a loop), you could try following, could be done in a single awk
itself.
awk 'BEGIN{FS=":"} {print "Average for student "$1 " is: " ($2+$3+$4)/3}' Input_file
Explanation: Adding detailed explanation for above.
awk ' ##Starting awk program from here.
BEGIN{ ##Starting BEGIN section of this program from here.
FS=":" ##Setting FS as colon here.
}
{
print "Average for student "$1 " is: " ($2+$3+$4)/3
##printing student name(1st column) and printing avg(adding 2nd, 3rd and 4th column) and dividing it with 3 here.
}
' Input_file ##Mentioning Input_file name here.
bash- find average of numbers in line
With some minor corrections, your code runs well:
while read -a rows
do
total=0
sum=0
for i in "${rows[@]}"
do
sum=`expr $sum + $i`
total=`expr $total + 1`
done
average=`expr $sum / $total`
echo $average
done <filename
With the sample input file, the output produced is:
1
5
7
5
2
5
Note that the answers are what they are because expr
only does integer arithmetic.
Using sed to preprocess for expr
The above code could be rewritten as:
$ while read row; do expr '(' $(sed 's/ */ + /g' <<<"$row") ')' / $(wc -w<<<$row); done < filename
1
5
7
5
2
5
Using bash's builtin arithmetic capability
expr
is archaic. In modern bash:
while read -a rows
do
total=0
sum=0
for i in "${rows[@]}"
do
((sum += $i))
((total++))
done
echo $((sum/total))
done <filename
Using awk for floating point math
Because awk does floating point math, it can provide more accurate results:
$ awk '{s=0; for (i=1;i<=NF;i++)s+=$i; print s/NF;}' filename
1
5.2
7.4
5.4
2.8
5.6
Calculate average execution time of a program using Bash
You could write a loop and collect the output of time
command and pipe it to awk
to compute the average:
avg_time() {
#
# usage: avg_time n command ...
#
n=$1; shift
(($# > 0)) || return # bail if no command given
for ((i = 0; i < n; i++)); do
{ time -p "$@" &>/dev/null; } 2>&1 # ignore the output of the command
# but collect time's output in stdout
done | awk '
/real/ { real = real + $2; nr++ }
/user/ { user = user + $2; nu++ }
/sys/ { sys = sys + $2; ns++}
END {
if (nr>0) printf("real %f\n", real/nr);
if (nu>0) printf("user %f\n", user/nu);
if (ns>0) printf("sys %f\n", sys/ns)
}'
}
Example:
avg_time 5 sleep 1
would give you
real 1.000000
user 0.000000
sys 0.000000
This can be easily enhanced to:
- sleep for a given amount of time between executions
- sleep for a random time (within a certain range) between executions
Meaning of time -p
from man time
:
-p
When in the POSIX locale, use the precise traditional format
"real %f\nuser %f\nsys %f\n"
(with numbers in seconds) where the number of decimals in the
output for %f is unspecified but is sufficient to express the
clock tick accuracy, and at least one.
You may want to check out this command-line benchmarking tool as well:
sharkdp/hyperfine
Assigned and calculate the average data with bash script?
If gawk
is available, would you please try the following:
gawk 'BEGIN {
IGNORECASE = 1 # make the regex case-insensitive
RS = "\r\n" # assign input record seoarator to CR+LF
ORS = "\n" # assign output record separator to LF
OFS = "\t" # assign output field separator to TAB
print "Sols", "Dose rate(average)" # print the header line
}
/START_SOL/ { # if the line contains "START_SOL"
gsub(/.*START_SOL=/, "")
sol = $0 # then assign "sol" to the value
}
c && !--c { # extract the 2nd line after "DOSE_B"
n++ # increment the number
sum += $0 # accumulate the dose rate
}
/DOSE_B/ {c = 2} # prepare for the 2nd next line
ENDFILE { # end of each file (available only with gawk)
print sol, sum / n # print sol and the average of dose rate
n = 0; sum = 0 # reset number and the sum
}
' /mnt/c/Users/taibo/Desktop/MSL_Script/Data/*.TXT | sort -nk1,1
- It extracts
sol
value anddose_b
rates out of each file. - Whenever the dose_b rate (second line after the keyword) is found,
the value is added tosum
and the countern
is incremented by 1. - At the end of each file, sol and the average of dose rate are printed.
- Finally the whole lines are numerically sorted by the
sol
value.
If you feel the execution time is slow, please try the Perl
alternative:
perl -015 -ne '
BEGIN {print "Sols\tDose rate(average)\n"}
if (/START_SOL=(\d+)/i) {$sol = $1}
elsif (/DOSE_B/i) {readline; $sum += readline; $n++}
elsif (eof) {printf("%s\t%f\n", $sol, $sum / $n); $sum = 0; $n = 0}
' /mnt/c/Users/taibo/Desktop/MSL_Script/Data/*.TXT | sort -nk1,1
How to use bash scripting to calculate an average?
Two problems: The spaces around the equal sign -- Bash is sensitive about this -- and the way you add (+) the two operands without evaluating with $()
.
I don't know exactly what your a.out
returns, but substituting it with a simple echo 1
, this adds up to 41:
moyenne=$(($moyenne + $(echo 1 2>&1 | tail -1)))
Related Topics
Linux History of All Commands Executed During Whole Day, Everyday
Restoring System Directories Permissions
Function to Search of Multiple Patterns Using Grep
How to Run a Binary File That Is Mach-O Executable I386 on Linux
Search Ip from a Text File in .Csv Log File, If Found Add New Column Next to It
Which Tool Has Replaced Gatttool in Bluez5
Expect Script Error Send: Spawn Id Exp4 Not Open While Executing
How to Put All Command Arguments in One Variable
Splitting a Large Directory into Smaller Ones in Linux
Reducing Privileges of a Process on Unix or Gnu/Linux
Bash Command to Search for Any Occurrence of Phrase and Return List of Files and Paths
Why Proc Process Faster Than Others