2011-10-30 32 views
1

我有一个数据集,则像下面,但更大: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])) 
} 

但数据集较大,我想一个循环做到这一点,我似乎无法获得工作。

+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块中,将所有的行读入一个大数组,然后遍历它,完成所有的数学计算,然后打印结果。

+0

我会如何修改这个,以便它会在下一行做同样的事情? – user1017243

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

请注意,只有记录总和被使用。因此,您可以通过查看两步来简化任务:

  1. 查找每条记录的总数。
  2. 计算总数的差异。

这可能是这样的:

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