Я пытаюсь написать сценарий, который будет анализировать данные из канала. Проблема в том, что один элемент описывается переменным количеством строк. Посмотрите на пример набора данных:

3 14 -30.48 17.23
4  1 -18.01 12.69
4  3 -11.01  2.69
8 12 -21.14 -8.76
8 14 -18.01 -5.69
8 12 -35.14 -1.76
9  2  -1.01 22.69
10 1 -88.88 17.28
10 1   -.88 14.28
10 1   5.88  1.28
10 1  -8.88 -7.28

В этом случае первая запись определяет событие, которому принадлежат следующие данные. В случае события номер 8 у нас есть данные в 3 строках. Чтобы упростить довольно сложную задачу, которую я пытаюсь решить, представим, что я хочу вычислить следующее выражение:

sum_i($2 * ($3 + $4))

Где i берется по всем строкам, принадлежащим данному элементу. Результат, который я хочу получить, будет выглядеть так:

3=-185.5   [14(-30.48+17.23) ]
4=-30.28   [1(-18.01+12.69) + 3(-11.01+2.69)]
8=-1106.4  [...]

Таким образом, мне нужен сценарий, который считывает все строки с одной и той же записью индекса.

Я новичок в AWK и начал изучать язык пару дней назад. Теперь я не уверен, смогу ли я добиться того, чего хочу. Следовательно:

  1. Возможно ли это с AWK?
  2. Если нет, то чем? САС?
  3. Если да, то как? Буду признателен, если предоставят ссылку, описывающую, как это можно реализовать.

Наконец, я знаю, что есть похожий вопрос: Могут ли шаблоны awk соответствовать нескольким строкам? однако у меня нет постоянного шаблона, разделяющего мои данные.

Благодарность!

1
Sasha 23 Дек 2015 в 16:15

3 ответа

Лучший ответ

Вы можете попробовать это:

awk '{ar[$1]+=$2*($3+$4)}
      END{for (key in ar) 
              {print key"="ar[key]}}' inputFile

Для каждого ввода строки мы выполняем желаемый расчет и суммируем результат в массиве. $1 служит ключом массива.
Когда весь файл прочитан, мы печатаем результаты в блоке END{...}.

Выходные данные для данного образца ввода:

4=-30.28
8=-1133.4
9=43.36
10=-67.2
3=-185.5

Если требуется сортировка вывода, вы можете взглянуть на функцию gawk asorti или команду sort в Linux (например, awk '{...} inputFile' | sort -n).

Это решение не требует сортировки входных данных.

3
F. Knorr 23 Дек 2015 в 19:34

Еще один похожий awk

$ awk -v OFS="=" 'NR==1{p=$1}
                  p!=$1{print p,s; s=0; p=$1}
                       {s+=$2*($3+$4)}
                    END{print p,s}' file

3=-185.5
4=-30.28
8=-1133.4
9=43.36
10=-67.2

Пс. Ваш расчет на «8» кажется неверным.

1
karakfa 23 Дек 2015 в 14:19
awk 'id!=$1{if(id){print id"="sum;sum=0};id=$1}{sum+=$2*($3+$4)} END{print id"="sum}' file
3=-185.5
4=-30.28
8=-1133.4
9=43.36
10=-67.2
3
bian 23 Дек 2015 в 13:58