user1116360
user1116360

Reputation: 422

Add numbers in special record

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

Answers (3)

potong
potong

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

Kent
Kent

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

Birei
Birei

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

Related Questions