awk - 跨ascii文件的行计算

时间:2014-12-03 14:01:08

标签: awk

我有一个具有以下结构的ascii文件:

1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,3,0,0,0,0.04,0,0,990,0
1,0,3,0,0,0,0.12,0,0,3760,0
1,0,3,0,0,0,0.21,0,0,5372,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
.
.
.

零代表“随机”数字我不需要照顾。

第3列等于3(总是三个块)我有 使用第7列和第10列执行一些计算:

我需要计算(0.04 * 990)+(0.12 * 3760)+(0.21 * 5372) 并将结果插入所有三行的第5列。 第10列中的值在下一个“三个块”中将有所不同。

以前我用awk做了很多ascii文件编辑,所以如果可能的话我也想在这里使用它。

我的主要问题是在找到第3列= 3后访问接下来的两行,然后再继续搜索两行。


结果应如下所示:

1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,3,0,1618.92,0,0.04,0,0,990,0
1,0,3,0,1618.92,0,0.12,0,0,3760,0
1,0,3,0,1618.92,0,0.21,0,0,5372,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
.
.
.

我希望我能够描述这个问题,如果不是只是问,我会澄清!


我试过了:

awk -F"," '$3 == "3"' in.dat > out.dat

并将其与

结合使用
awk -v "n=line numer" -v "s=string to insert" '(NR==n) { print s } 1' input-file

但我的主要问题是我不知道如何在第一行之后访问字段并将其用于公式中进行计算。

我真正需要使用的公式更复杂,但我只是在这里发布了一个简单的例子,因为将它改编为更复杂的解决方案是没有问题的。

2 个答案:

答案 0 :(得分:2)

在awk中

awk -F, '$3=="3"{a[++x]=$0;y+=($7*$10)}
         !x
         x==3{
            while(++i<=x){
                    split(a[i],b,",")
                    b[5]=y
                    for(j=1;j<length(b);j++)
                            c=j>1?c","b[j]:b[j]
                            print c
                            c=t
            }
            x=y=i=0
    }' file
  • 如果3是第三个字段,则将行保存到数组a并将总数添加到变量y
  • 如果x为0则打印
  • 如果x为3(即第三行),则阵列中的三条线将它们分成另一个数组
  • 将第5个元素更改为y(总计)。
  • 在另一个循环中重新创建行。
  • 打印线。

更短,更少资源饥饿的方式(归功于glenn jackmans回答给我的想法)

awk -F, '$3=="3"{a[++x]=$0;y+=($7*$10)}
         !x
         x==3{
            while(++i<=x){
                    $0=a[i]
                    $5=y
                    print
            }
            i=y=x=0
    }' test

答案 1 :(得分:1)

awk的getline命令可以很好地为你服务

awk -F, -v OFS=, '
    $3 == 3 {
        c = 0
        line1 = $0; c += $7 * $10; getline
        line2 = $0; c += $7 * $10; getline
        line3 = $0; c += $7 * $10
        $0 = line1; $5 = c; print
        $0 = line2; $5 = c; print
        $0 = line3; $5 = c
    }
    {print}
'

这对我的口味来说不够干净,但它只有3行并且非常易读。

DRY解决方案

awk -F, -v OFS=, '
    $3 == 3 {
        c = 0
        for(i=1;i<=3;i++)
        {line[i] = $0; c += $7 * $10; getline}
        for(i=1;i<=3;i++)
        {$0 = line[i]; $5 = c; print}
        next
    }1
'