ServerAID
Найти гайд, команду, тег… ⌘ K
Shell и скрипты

awk в Linux: обработка табличных данных и логов с примерами

awk — миниатюрный язык программирования для построчной обработки текста. Идеально подходит для работы с таблицами, CSV, логами и любыми данными со столбцами: автоматически разделяет каждую строку на поля и даёт удобный синтаксис фильтрации и преобразования. Разбираем базовый синтаксис, переменные, шаблоны, действия и десяток рецептов для повседневной работы администратора Ubuntu.

Что такое awk и зачем

awk — миниатюрный язык программирования и одновременно утилита Unix, специально заточенная под обработку структурированного текста (таблиц, CSV, логов). Название — аббревиатура имён авторов (Aho, Weinberger, Kernighan).

На Ubuntu по умолчанию установлен gawk (GNU awk) — самая полная реализация. Базовые синонимы:

awk --version       # покажет GNU Awk
which awk           # обычно /usr/bin/awk → ссылка на gawk

Что умеет awk:

  • Автоматически делит строку на поля по разделителю (по умолчанию — пробелы).
  • Применяет действия к строкам, удовлетворяющим шаблону.
  • Считает суммы, средние, группирует.
  • Форматирует вывод через printf.
  • Работает как полноценный язык: переменные, массивы, циклы, функции.

Главное преимущество перед grep/sed: awk думает столбцами. Если данные — таблица, awk-однострочник часто короче, чем bash-скрипт с cut, head, tail и арифметикой.

Базовый синтаксис

awk 'pattern { action }' file

Если pattern опущен — действие применяется к каждой строке. Если action опущен — печатается вся строка (как grep).

Самый простой пример:

# Печать первого столбца /etc/passwd (разделитель — двоеточие)
awk -F: '{print $1}' /etc/passwd

-F: — установить разделитель полей в двоеточие. $1 — первое поле, $0 — вся строка, NF — количество полей в строке, $NF — последнее поле.

Поля и разделители

# Все поля /etc/passwd
awk -F: '{print $1, $3, $7}' /etc/passwd
# вывод: root 0 /bin/bash
  • $0 — вся текущая строка.
  • $1, $2, ... $NF — отдельные поля.
  • NF — number of fields, количество полей в текущей строке.
  • NR — number of record, номер текущей строки (с 1).
  • FILENAME — имя текущего обрабатываемого файла.

Разделитель — FS (field separator) на входе и OFS (output field separator) на выходе:

# Заменить разделитель ;  на табуляцию
awk -F';' 'BEGIN{OFS="\\t"} {print $1, $2, $3}' input.csv

# CSV с возможными запятыми в значениях — простой не парсер
awk -F',' '{print $1}' file.csv

Для сложных CSV (с экранированными значениями) лучше специализированные инструменты (csvkit, mlr), но для простых данных awk достаточно.

Шаблоны: что фильтровать

Шаблон ставится перед { action }. Если строка ему соответствует — действие выполняется.

Регулярные выражения

# Строки, содержащие ERROR
awk '/ERROR/' /var/log/app.log

# Строки, начинающиеся с #
awk '/^#/' /etc/nginx/nginx.conf

# Несколько условий
awk '/ERROR|FATAL/' app.log

Регулярки в awk — ERE (как у grep -E), без экранирования alternations и групп.

Условия на поля

# Логи с кодом ответа 500 (предположим, $9 — статус)
awk '$9 == 500' /var/log/nginx/access.log

# Файлы тяжелее 1 МБ из ls -l ($5 — размер)
ls -l | awk '$5 > 1048576 {print $9, $5}'

# Только записи с непустым полем 4
awk '$4 != ""' data.txt

BEGIN и END

Специальные шаблоны, выполняемые до первой строки и после последней:

# Подсчитать сумму чисел во втором столбце
awk '{sum += $2} END {print sum}' data.txt

# Среднее значение
awk '{sum += $2; n++} END {print sum / n}' data.txt

# Заголовок таблицы
awk 'BEGIN{print "USER\\tUID"} {print $1, $3}' /etc/passwd

BEGIN особенно полезен для инициализации FS, OFS, объявления переменных. END — для агрегаций.

Диапазоны строк

# Строки между маркерами (включительно)
awk '/<start>/,/<end>/' file.txt

# С номера 10 по 20
awk 'NR >= 10 && NR <= 20' file.txt

Действия

print

Печатает поля через OFS:

awk '{print $2, $1}' file   # поменять местами 1-е и 2-е поля

printf

C-style форматирование:

# Аккуратная таблица
awk '{printf "%-15s %5d\\n", $1, $2}' data.txt

# Конвертация байт в МБ
df | awk 'NR>1 {printf "%-25s %.2f GB\\n", $1, $2/1024/1024}'

Присваивания и переменные

# Подсчитать строки, длиннее 80 символов
awk 'length($0) > 80 {n++} END {print n}' README.md

# Уникальные значения первой колонки (как sort -u)
awk '!seen[$1]++' file.txt

# Сумма по группам (первое поле — ключ)
awk '{sum[$1] += $2} END {for (k in sum) print k, sum[k]}' sales.txt

!seen[$1]++ — классический трюк для дедупликации без sort: использует ассоциативный массив seen, при первом появлении ключа значение становится 1, и !seen[$1]++ возвращает true; на втором появлении — false.

Десять рецептов

# 1. Имена пользователей с UID >= 1000 (обычные пользователи Linux)
awk -F: '$3 >= 1000 {print $1}' /etc/passwd

# 2. Топ-10 IP по запросам в nginx логе
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

# 3. Сумма размеров файлов в директории
ls -l | awk '{sum += $5} END {print sum/1024/1024 " MB"}'

# 4. Подсчитать строки в файле (без wc)
awk 'END {print NR}' file.txt

# 5. Удалить пустые строки и комментарии
awk '!/^$/ && !/^#/' /etc/nginx/nginx.conf

# 6. Заменить значение в N-м поле
awk -F: 'BEGIN{OFS=":"} {$7="/bin/zsh"; print}' /etc/passwd

# 7. Найти самые длинные строки в файле
awk '{print length($0), NR, $0}' file.txt | sort -rn | head

# 8. Конвертация табов в запятые
awk 'BEGIN{FS="\\t"; OFS=","} {$1=$1; print}' tabbed.txt > csv.txt

# 9. Считать только определённые HTTP-методы в логе
awk '$6 ~ /POST|PUT|DELETE/ {count[$6]++} END {for (m in count) print m, count[m]}' access.log

# 10. Выгрузить middle-колонку (не первую и не последнюю)
awk '{$1=""; $NF=""; print}' file.txt

awk vs sed vs grep

Три похожих инструмента, разные задачи:

Инструмент Идеален для Способ работы
grep поиск строк по шаблону фильтрация
sed замена/удаление подстрок потоковое редактирование
awk работа со столбцами и арифметика мини-язык программирования

Если задача — «найти строки» — grep. «Заменить текст» — sed. «Посчитать что-то по столбцам» — awk.

Часто все три встречаются в одной цепочке:

# Сколько уникальных IP сделало больше 100 запросов
grep "POST /api" /var/log/nginx/access.log \
  | awk '{print $1}' \
  | sort | uniq -c \
  | awk '$1 > 100 {print $2, $1}'

Производительность

awk обрабатывает несколько сот МБ/сек на одно ядро. Для гигабайтных файлов:

  • Не используйте регулярки на каждой строке без необходимости — фильтруйте сначала grep.
  • LANG=C awk ускоряет работу на ASCII-данных (без юникода).
  • Для параллелизма — GNU parallel: parallel --pipe --block 100M awk '...' < huge.log.

Современный gawk поддерживает многопроцессорный режим с MPFR — но для админских задач обычно хватает однопоточного.

Использование awk как полного языка

В скрипты awk можно вынести через -f:

# script.awk
BEGIN {
    FS = ","
    OFS = "\\t"
    print "USER", "TOTAL"
}
{
    sum[$1] += $2
    count[$1]++
}
END {
    for (user in sum) {
        printf "%-20s %d (avg %.2f)\\n", user, sum[user], sum[user]/count[user]
    }
}
awk -f script.awk sales.csv

Это уже полноценная аналитика, не однострочник. Когда задача переросла в скрипт на 50+ строк — обычно стоит переходить на Python с pandas; awk — для коротких операций.

Частые вопросы

Чем awk отличается от sed?

awk работает со строкой как с набором полей и поддерживает арифметику, переменные, массивы. sed — потоковый редактор для замены/удаления текста, минимум арифметики. Если задача звучит как «посчитать среднее во втором столбце» — это awk. Если «заменить foo на bar» — это sed.

Как узнать количество полей в строке?

Переменная NF (number of fields) автоматически содержит количество полей в текущей строке. awk '{print NF}' file — для каждой строки выведет своё количество полей. $NF — последнее поле.

Как задать другой разделитель полей?

Через -F в командной строке или присваивание FS в блоке BEGIN. Примеры: awk -F: '...' (двоеточие), awk -F"\\t" '...' (табуляция), awk 'BEGIN{FS=","} ...' (запятая). Для регулярки в качестве разделителя: awk -F'[,;|]' '...'.

Что такое NR и FNR?

NR — глобальный счётчик строк, продолжает считать через файлы. FNR — счётчик внутри текущего файла, сбрасывается при переходе к следующему. Полезно при обработке нескольких файлов: awk 'FNR==1 {print "==> " FILENAME " <=="} {print}' file1 file2.

Можно ли использовать awk для CSV с экранированными запятыми?

Базовый awk — нет, потому что не понимает кавычек. Для простого CSV (без вложенных запятых) — awk -F',' работает. Для сложного — используйте mlr (Miller) или csvkit. Альтернатива — gawk с FPAT: awk 'BEGIN{FPAT="([^,]+)|(\\"[^\\"]+\\")"} ...', но это уже хрупко.

Что запомнить

  • awk — мини-язык для построчной работы с таблицами и логами.
  • Базовый синтаксис: awk 'pattern { action }' file.
  • Поля доступны как $1, $2, ..., $NF. Разделитель — -F или FS в BEGIN.
  • Переменные: NR (строка), NF (количество полей), FILENAME.
  • Специальные шаблоны: BEGIN (до обработки), END (после), regex /.../, условия на поля.
  • Действия: print, printf, присваивания, массивы arr[key]++.
  • Трюк дедупликации: awk '!seen[$1]++'.
  • Связка с grep и sed: grep фильтрует, awk считает по столбцам, sed редактирует.
  • Большие задачи переносить в -f script.awk или Python.

Похожие материалы

Shell и скрипты

grep в Linux: поиск по тексту с регулярками и примерами для Ubuntu

grep — главный инструмент поиска по содержимому файлов в Linux. Умеет работать с регулярными выражениями POSIX и PCRE, рекурсивно обходить директории, считать совпадения, показывать контекст вокруг строки. Разбираем синтаксис, ключевые флаги, тонкости с регулярками и десяток рецептов для повседневной работы администратора Ubuntu.

Редакция
Shell и скрипты

find в Linux: руководство по поиску файлов с примерами для Ubuntu

find — самый мощный инструмент поиска файлов в Linux. В отличие от locate он смотрит файловую систему вживую, поддерживает фильтрацию по имени, размеру, времени изменения, правам, владельцу и умеет выполнять действие над найденным. Разбираем синтаксис, ключевые предикаты и десяток рецептов, которые покрывают 95% реальных задач администратора Ubuntu.

Редакция
Shell и скрипты

sed на Linux: замена строк, правка in-place и регулярки

sed (stream editor) — стандартная команда Linux для построчной обработки текста: замена, удаление, печать строк по шаблону. Работает с потоком (pipe) или файлами, поддерживает in-place редактирование. Базовый инструмент шелл-скриптов после `grep` и `awk`.

Редакция
Shell и скрипты

wget на Linux: скачивание файлов, дозакачка и зеркало сайта

wget — стандартная утилита Linux для скачивания файлов по HTTP, HTTPS и FTP. Умеет дозакачивать прерванное, ходить рекурсивно по ссылкам, ограничивать скорость и работать без интерактива — поэтому это базовый инструмент скриптов установки, скачивания дистрибутивов и зеркалирования сайтов.

Редакция