Вы хотели сделать что-то подобное? Это единственный способ понять ваш сценарий.
awk -v OFS=$'\t' '
FNR == 1 { $5 = "sdev" ; print }
FNR > 1 { a = $4 # field 4 is 'avg'
n = NF-1 # exclude the 'avg' field from the ss calculations.
for (i=1; i <= n; i++) { ss += ($i - a)^2 }
$5 = sqrt(ss/n)
print
}' inputfile
Примечание. $ i
в строке для
относится НЕ к значению i
, а к полю ввода с номером i
- т.е. он проходит через $ 1
, $ 2
и $ 3
. Это может быть неочевидно для пользователей оболочки или perl
, где (скалярные) переменные обычно имеют префикс $
.
NF
- это количество полей в строке, а FNR
- это номер записи (строки) текущего входного файла (так что этот awk
скрипт поддерживает множественный ввод файлы, каждый со своей собственной строкой заголовка. Если когда-либо будет только один входной файл за раз, вы можете использовать NR
вместо FNR
).
Пример вывода:
1 2 3 avg sdev
23.3107 20.0372 21.7236 21.6905 1.33661
Вот еще одна версия, которая работает с любым количеством полей в строке. Предполагается, что поле последнее строки содержит среднее значение всех предыдущих полей в этой строке.
$ NF
относится к значению последнего поля (т. Е. «Avg»), а $ new
относится к (последнее поле + 1), т. Е. Присвоение ему значения добавляет новое поле до конца строки.
awk -v OFS=$'\t' '
FNR == 1 { new = NF+1 # number of new field to add
$new = "sdev"
print
}
FNR > 1 { a = $NF # last field is 'avg'
n = NF-1 # exclude the 'avg' field from the ss calculations.
for (i=1; i <= n; i++) { ss += ($i - a)^2 }
$new = sqrt(ss/n)
print
}' inputfile
Пример вывода с 5 значениями плюс среднее значение в каждой строке ввода:
1 2 3 4 5 avg sdev
23.3107 20.0372 21.7236 20.5328 21.2016 21.3611 1.13107