С помощью awk просуммируйте и усредните столбец, отфильтровав строки по полю
Из nginx-лога access.log нужны суммарные и средние отданные байты только по успешным запросам. Поля разделены пробелами; код статуса — поле $9, размер ответа в байтах — поле $10.
Ограничения: один вызов awk, один проход; учитывать лишь строки со статусом 200; не делить на ноль, если таких строк нет.
# IP - - [time] "GET /path HTTP/1.1" 200 5120
awk '???' access.log
Допишите программу awk так, чтобы она печатала сумму и среднее.
Фильтруйте шаблоном, накапливайте в теле, печатайте в END: awk '$9==200 { sum+=$10; n++ } END { if (n) print sum, sum/n }' access.log. Шаблон $9==200 запускает блок лишь на подходящих строках, sum+=$10 суммирует поле байтов, n++ их считает, а END срабатывает по концу ввода. Проверка n не даёт делить на ноль.
- ✗Писать
$9=200(присваивание, всегда истина) вместо$9==200(сравнение) - ✗Делить на
NR(все строки ввода), а не на отфильтрованный счётчикn - ✗Печатать в теле на каждой строке, а не один раз в блоке
END
- →Почему
$9=200совпадает с каждой строкой, а$9==200фильтрует верно? - →Как сгруппировать итоги по каждому коду статуса, а не только по
200?
Решение
awk устроен как «шаблон { действие }»: действие выполняется на строках, где шаблон истинен. Суммирование идёт в теле, а итог печатается в END — блоке, который срабатывает один раз после всего ввода.
awk '$9==200 { sum += $10; n++ } END { if (n) print sum, sum/n }' access.log
выполняется тело; остальные пропускаются.
if (n) защищает от деления на ноль при пустой выборке.
$9==200— шаблон-условие (==, сравнение). На строках со статусом 200sum += $10копит байты,n++считает подходящие строки.END { if (n) print sum, sum/n }— по концу ввода печатает сумму и среднее;
Главные ловушки: $9=200 — это присваивание (всегда истинно, «пройдут» все строки), а делить надо на n, а не на NR (число всех строк ввода). Один проход, один вызов awk — конвейер с grep/bc не нужен.