在特殊记录中添加数字

时间:2011-12-28 13:18:17

标签: shell sed awk

我需要以下帮助,我有这些记录:

2 8 [4] 2 2 5 8 4 5 6 1

3 4 1 2 4 8 9

我应该添加突出显示的列,并打印出总和和平均值。

因此,如果记录包含“[]” - s,我们应该在此字符+ 1之后开始求和形式,否则从第4列开始到结束。

我希望这个输出:

2 8 [4] 2 2 5 8 4 5 6 1 31 4.4285

3 4 1 2 4 8 9 23 5.75

提前致谢!

3 个答案:

答案 0 :(得分:3)

一种方式:

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 
}

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

运行脚本:

awk -f script.awk infile

结果:

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

答案 1 :(得分:1)

awk oneliner可以解决这个问题:

 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

试验:

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

答案 2 :(得分:0)

这可能是sed / bash解决方案适合您:

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