Reputation: 422
I need help in the following, I have these kind of records:
2 8 [4] 2 2 5 8 4 5 6 1
3 4 1 2 4 8 9
I should add the highlighted columns, and print out the sum, and the average.
So, if the record contain "[]"-s, we should begin the summing form after this character + 1, else from the 4th column to the end.
I would expect this output:
2 8 [4] 2 2 5 8 4 5 6 1 31 4.4285
3 4 1 2 4 8 9 23 5.75
Thanks in advance!
Upvotes: 0
Views: 83
Reputation: 58558
This might sed/bash solution work for you:
sum(){ { printf "a+=%d;" $@; echo "scale=4; a"; } | bc -l; }
avg(){ { printf "a+=%d;" $@; echo "scale=4; a/$#"; } | bc -l; }
set -f sum avg
sed 's/^.*]\s*\S*\s*\(.*\)/& $(sum \1) $(avg \1)/;ta;s/^\(\s*\S*\)\{3\}\s*\(.*\)/& $(sum \2) $(avg \2)/;:a;s/.*/echo "&"/' file | sh
Upvotes: 0
Reputation: 195229
an awk oneliner can solve this problem:
awk -F'] ' '{s=$NF; sum=0;avg=0;split(s,n," "); idx=NF>1?2:4;for(x=idx;x<=length(n);x++)sum+=n[x]; avg=sum/(length(n)-idx+1); print $0" "sum" "avg;} inputFile
test:
kent$ cat v
2 8 [4] 2 2 5 8 4 5 6 1
3 4 1 2 4 8 9
1 15 [4] [8] [12] 4 1 4 8 3 7 9 4 8 9 7 9 1
kent$ awk -F'] ' '{s=$NF; sum=0;avg=0;split(s,n," "); idx=NF>1?2:4;for(x=idx;x<=length(n);x++)sum+=n[x]; avg=sum/(length(n)-idx+1); print $0" "sum" "avg;} ' v
2 8 [4] 2 2 5 8 4 5 6 1 31 4.42857
3 4 1 2 4 8 9 23 5.75
1 15 [4] [8] [12] 4 1 4 8 3 7 9 4 8 9 7 9 1 70 5.83333
Upvotes: 1
Reputation: 36282
One way:
Content of script.awk:
{
## If exists in the line any number surrounded with square brackets...
if ( $0 ~ /\[[0-9]+\]/ ) {
## Find its position (beginning the search from the end because I
## want the last one, and begin the count position two numbers later.
for ( i = NF; i >= 1; i-- ) {
if ( $i ~ /^\[[0-9]+\]$/ ) {
pos = i + 2
break
}
}
} else {
## Default position when not found any square brackets.
pos = 4
}
## Sum numbers and count them from the position set before until last number.
for ( j = pos; j <= NF; j++ ) {
sum += $j
count++
}
## Print to output.
printf "%s %.5g %.5g\n", $0, sum, (sum / count)
sum = 0
count = 0
pos = 0
}
Content of infile:
2 8 [4] 2 2 5 8 4 5 6 1
3 4 1 2 4 8 9
1 15 [4] [8] [12] 4 1 4 8 3 7 9 4 8 9 7 9 1
Run the script:
awk -f script.awk infile
Result:
2 8 [4] 2 2 5 8 4 5 6 1 31 4.42857
3 4 1 2 4 8 9 23 5.75
1 15 [4] [8] [12] 4 1 4 8 3 7 9 4 8 9 7 9 1 70 5.8333
Upvotes: 3