Awk вычитать записи - PullRequest
       5

Awk вычитать записи

1 голос
/ 31 октября 2011

У меня есть набор данных, похожий на следующий, но гораздо больший:

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 ]

1 голос
/ 31 октября 2011
awk '
  BEGIN { getline; split($0,v1) }
  { 
    split($0,v2); 
    result=0; 
    for (i in v1) { 
      result += v1[i]-v2[i];
    }
    print result
  }
'
1 голос
/ 31 октября 2011

Одна очевидная возможность будет что-то в этом порядке:

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 голосов
/ 31 октября 2011

Обратите внимание, что когда-либо используются только суммы записей. Таким образом, вы можете упростить задачу, рассматривая ее в два этапа:

  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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...