#awk
#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]))
}
однако набор данных большой, и я хотел бы, чтобы для этого использовался цикл, который, похоже, не работает.
Комментарии:
1. И что вы хотите сделать с результатом? Распечатать все значения?
Ответ №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("%dn", total);
}
Обратите внимание, что при этом не предпринимается никаких попыток обнаружить или разумно обработать неверный ввод.
Редактировать (чтобы соответствовать отредактированному вопросу):
Учитывая, что вы изменили вопрос, чтобы задать, вам, очевидно, нужно прочитать все данные в массив, затем пройти по массиву и сложить различия между записями. Это больше не очень хорошо согласуется с тем, как работает awk, поэтому моим непосредственным советом было бы использовать что-то другое. Если вы все равно настаиваете на использовании awk, вы могли бы в принципе поместить всю обработку в BEGIN
блок, считывая все строки в большой массив, затем просматривая его, выполняя все вычисления, а затем распечатывая результаты.
Комментарии:
1. Как мне изменить это, чтобы оно делало то же самое в следующих строках?
Ответ №2:
awk '
BEGIN { getline; split($0,v1) }
{
split($0,v2);
result=0;
for (i in v1) {
result = v1[i]-v2[i];
}
print result
}
'
Ответ №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