用awk计算梯度之和

时间:2014-08-04 13:15:40

标签: bash awk

我有一个包含4列的文件,例如:

A  B  C  D
1  2  3  4
10 20 30 40
100 200 300 400
.
.
.

我可以计算列B到D与A的梯度,例如以下命令:

NR>1{print $0,($2-b)/($1-a)}{a=$1;b=$2}' file

如何打印渐变之和作为文件中的第5列?结果应该是:

A  B  C  D sum
1  2  3  4 1+2+3+4=10
10 20 30 40 (20-2)/(10-1)+(30-3)/(10-1)+(40-4)/(10-1)=9
100 200 300 400 (200-20)/(100-10)+(300-30)/(100-10)+(400-40)/(100-10)=9
.
.
.

2 个答案:

答案 0 :(得分:1)

awk 'NR == 1 { print $0, "sum"; next } { if (NR == 2) { sum = $1 + $2 + $3 + $4 } else { t = $1 - a; sum = ($2 - b) / t + ($3 - c) / t + ($4 - d) / t } print $0, sum; a = $1; b = $2; c = $3; d = $4 }' file

输出:

A  B  C  D sum
1  2  3  4 10
10 20 30 40 9
100 200 300 400 9

使用... | column -t

A    B    C    D    sum
1    2    3    4    10
10   20   30   40   9
100  200  300  400  9

更新

#!/usr/bin/awk -f
NR == 1 {
    print $0, "sum"
    next
}
{
    sum = 0
    if (NR == 2) {
        for (i = 1; i <= NF; ++i)
            sum += $i
    } else {
        t = $1 - a[1]
        for (i = 2; i <= NF; ++i)
            sum += ($i - a[i]) / t
    }
    print $0, sum
    for (i = 1; i <= NF; ++i)
        a[i] = $i
}

用法:

awk -f script.awk file

答案 1 :(得分:1)

如果对第一行数字应用与第二行相同的逻辑,将每列的初始值设为0,则得到9作为总和的结果(原来在你的问题中) 。该方法使用循环来累积从第二个字段到最后一个字段的梯度之和。它使用的事实是,在第一轮中,数组a中未初始化的值计算为0:

awk 'NR==1 { print $0, "sum"; next } 
{
    s = 0
    for(i=2;i<=NF;++i) s += ($i-a[i])/($1-a[1]) # accumulate sum
    for(i=1;i<=NF;++i) a[i] = $i      # fill array to be used for next iteration
    print $0, s
}' file

如果需要,可以将它们全部打包到一行,但记得用分号分隔语句。仅使用for循环if时,它也会略短一些:

awk 'NR==1{print$0,"sum";next}{s=0;for(i=1;i<=NF;++i)if(i>1)s+=($i-a[i])/($1-a[1]);a[i]=$i;print$0,s}' file

输出:

A  B  C  D sum
1  2  3  4 9
10 20 30 40 9
100 200 300 400 9