Как awk заменяет 10 команд Bash
Привет, Хабр! Когда я только начинал работать с Linux, каждую задачу обрабатывал через кучку пайпов. Потом мой коллега сказал мне: «Завязывай с этим, попробуй awk». Ну, я попробовал. И это действительно удобно. Сегодня я расскажу, как awk может заменить несколько привычных команд bash.
Выборка столбцов
Классика жанра: есть CSV‑файл, и надо взять второй и четвертый столбцы. Обычно вы бы написали:
cut -d',' -f2,4 file.csv
Но! Зачем cut
, если есть awk? Выглядит намного красивее:
awk -F',' '{if (NF >= 4) print $2, $4}' file.csv
Никаких точек с запятыми, странных пайпов. Все в одну строчку. Выглядит приятно.
Фильтрация строк по ключевому слову
Вы смотрите логи. Сервер падает (как обычно), и вы ищете строки с »Error». Обычно это grep
:
grep "Error" logs.txt
С awk это выглядит так:
awk '/Error/' logs.txt
awk — это почти как SQL для текстовых файлов. Можно использовать любой шаблон
awk '/^Error [0-9]{3}:/' logs.txt
Вот вам и фильтрация ошибок по HTTP-коду.
Подсчёт строк с условием
«Сколько раз я был прав?» — спросите вы после пары ошибок. С grep -c
это просто:
grep -c "Success" logs.txt
А теперь смотрим, как это делает awk:
awk '/Success/ {count++} END {print count}' logs.txt
Здесь важно слово END
. Оно активируется после обработки всех строк.
Замена текста
Допустим, вам нужно заменить »проблема» на »задача» в файле. С sed
это так:
sed 's/проблема/задача/g' file.txt
А вот и awk, который делает то же самое:
awk '{gsub(/проблема/, "задача"); print}' file.txt
Кстати, это прекрасно работает с JSON.
Уникальные строки
Ну кто из нас не сортировал строки через sort | uniq
? Пример:
sort file.txt | uniq
С awk можно проще:
awk '!seen[$0]++' file.txt
seen
— это массив. Если строка ещё не встречалась, мы её выводим.
Подсчёт слов
Надо быстро посчитать, сколько слов в файле? Берем wc -w
:
wc -w file.txt
Но мы тут за awk, так что:
awk '{count += NF} END {print count}' file.txt
NF
— количество полей (читай: слов) в строке. Кажется, что избыточно? Возможно. Но если вы захотите условие «только строки, где слов больше 5», это уже выглядит удобней.
Вывод строк по диапазону
Нужно вывести строки с 10 по 20? Старый добрый sed
:
sed -n '10,20p' file.txt
С awk всё просто:
awk 'NR>=10 && NR<=20' file.txt
NR
— это текущий номер строки.
Вычисление среднего
А вот это совсем интересно. Есть файл с числами в первом столбце, и вы хотите их среднее. Обычно такой Bash:
awk '{sum += $1} END {print sum/NR}' numbers.txt
А теперь сделаем это с проверкой на случай, если файл пустой:
awk '{sum += $1; count++} END {if (count > 0) print sum/count; else print "Нет данных"}' numbers.txt
Конечно, awk — инструмент хороший, но и у него есть свои недостатки.
Обратная сторона awk
Производительность на больших данных. Для обработки очень больших файлов awk может быть менее эффективен, чем инструменты вроде
sed
,grep
или того же Python. Иногда проще написать скрипт на Python сpandas
, чем шаманить с awk на терабайтном логе.Сложность отладки. Если awk-скрипт становится длинным и запутанным, отладка превращается в головную боль. Нет ни встроенного дебаггера, ни удобных средств для профилирования.
Ограниченная поддержка. Несмотря на всю свою мощь, awk не поддерживает сложные структуры данных или современные подходы к программированию (ну, потому что это всё-таки инструмент 70-х годов). Иногда проще подключить полноценный язык программирования.
Зависимость от реализации. Существуют разные версии awk (например,
gawk
,mawk
,nawk
), и некоторые возможности могут отличаться между ними. Если ваш скрипт запускается на одном сервере, это не значит, что он так же будет работать на другом.
Такие дела. А какой у вас опыт работы с awk? Делитесь в комментариях.
Приглашаю вас на бесплатные вебинары курса Administrator Linux. Professional: