Awk减去记录

时间:2011-10-30 20:01:00

标签: awk

我有一个类似于以下的数据集,但是要大得多:

5 6 9
2 4 6
4 5 1

我希望能够从当前记录中减去每个记录中的每个字段,然后将它们一起添加并存储结果。例如,我想要,从第一行(5-2)+(6-4)+(9-6)=结果开始。并且(5-4)+(6-5)和(9-1)。也适用于所有其他线路,例如第二线(2-4)+(4-5)+(6-1)和(2-5)+(4-6)+(6-9)等我可以按照以下方式手动执行此操作:

{
     if (max_nf < NF)
          max_nf = NF
     max_nr = NR
     for (x = 1; x <= NF; x++)
          vector[x, NR] = $x
}

END { result = ((vector[1,1] - vector[1,2]) + (vector[2,1] - vector[2,2]) + (vector[3,1] - vector[3,2]))
}

然而,数据集很大,我想要一个循环来做这个,我似乎无法工作。

3 个答案:

答案 0 :(得分:1)

这个订单有一个明显的可能性:

BEGIN { getline; fields = NF+1; for (i=1; i<fields; i++) first[i] = $i; }

    { 
      total = 0;
      for (field = 1; field < fields; field++)  
          total += first[field] - $field;
      printf("%d\n", total);
    }

请注意,这不会尝试智能地检测或处理错误的输入。

编辑(以适应编辑过的问题):

鉴于您已经改变了要问的问题,您显然需要将所有数据读入数组,然后遍历数组并添加记录之间的差异。这不再适合awk的工作原理,所以我的建议是使用其他东西。如果你仍然坚持使用awk,你基本上可以将所有处理放入BEGIN块,将所有行读入一个大数组,然后遍历它,完成所有数学运算,然后打印结果。 / p>

答案 1 :(得分:1)

awk '
  BEGIN { getline; split($0,v1) }
  { 
    split($0,v2); 
    result=0; 
    for (i in v1) { 
      result += v1[i]-v2[i];
    }
    print result
  }
'

答案 2 :(得分:0)

请注意,只使用了记录的总和。因此,您可以通过将其视为两个步骤来简化任务:

  1. 查找每条记录的总数。
  2. 计算总数的差异。
  3. 这可能看起来像:

    cat data | # generate the data in whatever fashion
      awk '{ for (n=1; n<=NF; n++) 
               recsum[NR]+=$n
           } 
           END { 
             for (n=1; n<=NR; n++) 
               for (m=n+1; m<=NR; m++) 
                 print n, m, recsum[n]-recsum[m] }'
    

    对于问题中给出的样本数据,这会产生预期结果:

    1 2 8
    1 3 10
    2 3 2