Reputation: 19
I have a project in Bash and I need a way of calculating averages of students and adding those averages in a text file. The text file is the following:
:NOM Prenom:CODE :.Tp1 :.Intra:.Tp2 :.Tp3 :.Final :.TP4 :.Moy:.Lettre:
actarusx:Actarus :ACTA28658105 : 45.5: 75.00:100.0: 95.0: 48.50: 90.0:
alcorxxx:Alcor :ALCO18083408 : 83.0: 64.75: 95.0: 87.5: 74.00: 97.0:
venusiax:Venusia :VENU13097708 : 83.0: 55.00: 95.0: 87.5: 41.50: 97.0:
phenicia:Phenicia :PHEN14100790 : 94.0: 50.50: 95.0: 95.0: 59.50: 99.0:
mizarxxx:Mizar :MIZA22128106 : 98.0: 95.50: 95.0:100.0: 80.50: 90.0:
procyonx:Procyon :PROC01033701 : 99.0: 99.50:100.0: 95.0: 98.00:100.0:
flamxxxx:Flam :FLAM26077904 : 89.0: 37.25: 97.5: 87.5: 63.50: 97.0:
johannxx:johann :JOHA23058000 : 94.0: 99.25:100.0: 95.0: 36.00:100.0:
wrightxx:Wright :WRIG21058103 : 99.0: 100.0:100.0:100.0: 100.0: 97.0:
cragxxxx:Grag :CRAG05018002 : 99.0: 90.00: 90.0:100.0: 97.00: 99.0:
malaxxxx:Mala :MALA09557914 : 96.0: 69.50:100.0:100.0: 34.00: 47.0:
I want to calculate the total average of TP1,2,3,4, Intra and Final. Once I have the average for each student (one student per line), I want to add the average under the column called Moy:. Note: For some reason, the categories all got moved around so the first line of floats is associated with tp1 and so forth.
At the moment I have:
nbline=0
while read line; do
if[ $nbline -eq 0 ]; then #To skip the first line with each categories
let nbline+=1
else
# Code that allows me to get the grades for each categories (already provided by the teacher)
# eg. for the first student the code will do tp1=45.5, intra=75, etc...
# Code that allows me to calculate the average (already provided by the teacher)
# moy is the average found
Once I find moy, I'm not sure how to add it in the column Moy: of each student. This is my first time coding in unix/linux and my teacher didn't spend a lot of time (if any at all) teaching us the different commands so help would be greatly appreciated.
Thank you very much
Upvotes: 1
Views: 113
Reputation: 8715
Simple is Good
λ cat input.txt
:NOM Prenom:CODE :.Tp1 :.Intra:.Tp2 :.Tp3 :.Final :.TP4 :.Moy:.Lettre:
actarusx:Actarus :ACTA28658105 : 45.5: 75.00:100.0: 95.0: 48.50: 90.0:
alcorxxx:Alcor :ALCO18083408 : 83.0: 64.75: 95.0: 87.5: 74.00: 97.0:
venusiax:Venusia :VENU13097708 : 83.0: 55.00: 95.0: 87.5: 41.50: 97.0:
phenicia:Phenicia :PHEN14100790 : 94.0: 50.50: 95.0: 95.0: 59.50: 99.0:
mizarxxx:Mizar :MIZA22128106 : 98.0: 95.50: 95.0:100.0: 80.50: 90.0:
procyonx:Procyon :PROC01033701 : 99.0: 99.50:100.0: 95.0: 98.00:100.0:
flamxxxx:Flam :FLAM26077904 : 89.0: 37.25: 97.5: 87.5: 63.50: 97.0:
johannxx:johann :JOHA23058000 : 94.0: 99.25:100.0: 95.0: 36.00:100.0:
wrightxx:Wright :WRIG21058103 : 99.0: 100.0:100.0:100.0: 100.0: 97.0:
cragxxxx:Grag :CRAG05018002 : 99.0: 90.00: 90.0:100.0: 97.00: 99.0:
malaxxxx:Mala :MALA09557914 : 96.0: 69.50:100.0:100.0: 34.00: 47.0:
awk -F: 'NR==1;NR>1{print $0 ($4+$5+$6+$7+$8+$9)/6}' input.txt
:NOM Prenom:CODE :.Tp1 :.Intra:.Tp2 :.Tp3 :.Final :.TP4 :.Moy:.Lettre:
actarusx:Actarus :ACTA28658105 : 45.5: 75.00:100.0: 95.0: 48.50: 90.0: 75.6667
alcorxxx:Alcor :ALCO18083408 : 83.0: 64.75: 95.0: 87.5: 74.00: 97.0: 83.5417
venusiax:Venusia :VENU13097708 : 83.0: 55.00: 95.0: 87.5: 41.50: 97.0: 76.5
phenicia:Phenicia :PHEN14100790 : 94.0: 50.50: 95.0: 95.0: 59.50: 99.0: 82.1667
mizarxxx:Mizar :MIZA22128106 : 98.0: 95.50: 95.0:100.0: 80.50: 90.0: 93.1667
procyonx:Procyon :PROC01033701 : 99.0: 99.50:100.0: 95.0: 98.00:100.0: 98.5833
flamxxxx:Flam :FLAM26077904 : 89.0: 37.25: 97.5: 87.5: 63.50: 97.0: 78.625
johannxx:johann :JOHA23058000 : 94.0: 99.25:100.0: 95.0: 36.00:100.0: 87.375
wrightxx:Wright :WRIG21058103 : 99.0: 100.0:100.0:100.0: 100.0: 97.0: 99.3333
cragxxxx:Grag :CRAG05018002 : 99.0: 90.00: 90.0:100.0: 97.00: 99.0: 95.8333
malaxxxx:Mala :MALA09557914 : 96.0: 69.50:100.0:100.0: 34.00: 47.0: 74.4167
-F:
sets :
as the field separator{ action }
means print the line. For example, the following commands are identical:
awk '1{ print $0 }
awk '1{ print }
awk '1'
1
as pattern condition. awk
treats non-empty string and non-zero number as true
. For example, the following commands are identical:
awk '1'
awk '"foo"'
awk
concatenations are indicated by white spaces thus print $0 ($4+$5+$6+$7+$8+$9)/6
would print the whole record $0
followed by ($4+$5+$6+$7+$8+$9)/6
.Upvotes: 2
Reputation: 3975
LC_ALL="C"
start_col=4
end_col=9
output_col=10
delimiter=":"
awk \
-F"$delimiter" \
-v "start=$start_col" \
-v "end=$end_col" \
-v "output=$output_col" '
BEGIN {OFS = FS}
NR == 1 { print }
NR !=1 {
sum=0
for (i=start; i<=end; i++) sum=sum+$i
$(output)=" "sprintf("%.2f", sum/((end+1)-start))
print
}' file.txt
Output:
:NOM Prenom:CODE :.Tp1 :.Intra:.Tp2 :.Tp3 :.Final :.TP4 :.Moy:.Lettre:
actarusx:Actarus :ACTA28658105 : 45.5: 75.00:100.0: 95.0: 48.50: 90.0: 75.67
alcorxxx:Alcor :ALCO18083408 : 83.0: 64.75: 95.0: 87.5: 74.00: 97.0: 83.54
venusiax:Venusia :VENU13097708 : 83.0: 55.00: 95.0: 87.5: 41.50: 97.0: 76.50
phenicia:Phenicia :PHEN14100790 : 94.0: 50.50: 95.0: 95.0: 59.50: 99.0: 82.17
mizarxxx:Mizar :MIZA22128106 : 98.0: 95.50: 95.0:100.0: 80.50: 90.0: 93.17
procyonx:Procyon :PROC01033701 : 99.0: 99.50:100.0: 95.0: 98.00:100.0: 98.58
flamxxxx:Flam :FLAM26077904 : 89.0: 37.25: 97.5: 87.5: 63.50: 97.0: 78.62
johannxx:johann :JOHA23058000 : 94.0: 99.25:100.0: 95.0: 36.00:100.0: 87.38
wrightxx:Wright :WRIG21058103 : 99.0: 100.0:100.0:100.0: 100.0: 97.0: 99.33
cragxxxx:Grag :CRAG05018002 : 99.0: 90.00: 90.0:100.0: 97.00: 99.0: 95.83
malaxxxx:Mala :MALA09557914 : 96.0: 69.50:100.0:100.0: 34.00: 47.0: 74.42
Upvotes: 1
Reputation: 22012
Would you please try the following:
#!/bin/bash
while read -r line; do
if (( nr++ == 0 )); then # header line
echo "$line"
else
mapfile -d: -t a <<< "$line" # assign array "a" to the columns
ave=$(echo "scale=2; ( $(IFS=+; echo "${a[*]:3:6}") ) / 6" | bc)
printf "%s%6s\n" "$line" "$ave"
fi
done < file.txt
Output:
:NOM Prenom:CODE :.Tp1 :.Intra:.Tp2 :.Tp3 :.Final :.TP4:.Moy:.Lettre:
actarusx:Actarus :ACTA28658105 : 45.5: 75.00:100.0: 95.0: 48.50: 90.0: 75.66
alcorxxx:Alcor :ALCO18083408 : 83.0: 64.75: 95.0: 87.5: 74.00: 97.0: 83.54
venusiax:Venusia :VENU13097708 : 83.0: 55.00: 95.0: 87.5: 41.50: 97.0: 76.50
phenicia:Phenicia :PHEN14100790 : 94.0: 50.50: 95.0: 95.0: 59.50: 99.0: 82.16
mizarxxx:Mizar :MIZA22128106 : 98.0: 95.50: 95.0:100.0: 80.50: 90.0: 93.16
procyonx:Procyon :PROC01033701 : 99.0: 99.50:100.0: 95.0: 98.00:100.0: 98.58
flamxxxx:Flam :FLAM26077904 : 89.0: 37.25: 97.5: 87.5: 63.50: 97.0: 78.62
johannxx:johann :JOHA23058000 : 94.0: 99.25:100.0: 95.0: 36.00:100.0: 87.37
wrightxx:Wright :WRIG21058103 : 99.0: 100.0:100.0:100.0: 100.0: 97.0: 99.33
cragxxxx:Grag :CRAG05018002 : 99.0: 90.00: 90.0:100.0: 97.00: 99.0: 95.83
malaxxxx:Mala :MALA09557914 : 96.0: 69.50:100.0:100.0: 34.00: 47.0: 74.41
mapfile -d: -t a <<< "$line"
splits the input line on colons and assign
array a
to the columns.$(IFS=+; echo "${a[*]:3:6}")
outputs the columns from the 4th to the 9th
delimited by +
sign so the bc
command can caluculate the sum of the
columns.-scale=2
and the width %6s
in printf
format.Upvotes: 1