Gymterview
middle

Как использовать awk для обработки текста?

awk — мощный язык обработки структурированного текста. По умолчанию разделяет каждую строку на поля по пробелам/табуляциям и позволяет работать с каждым полем отдельно.

Аналогия

Если grep — это фильтр (пропускает или нет), а sed — корректор (заменяет текст), то awk — это аналитик с калькулятором: он умеет разбирать таблицы на колонки, считать суммы, фильтровать по условиям и форматировать отчёты.

Базовые понятия

  • $0 — вся строка целиком
  • $1, $2, … $N — поля (колонки) строки
  • NR — номер текущей строки (Number of Record)
  • NF — количество полей в текущей строке (Number of Fields)
  • FS — разделитель полей (Field Separator), по умолчанию пробел/таб
  • OFS — разделитель полей на выходе (Output Field Separator)

Выбор колонок

Пример
# Вывести первую колонку
awk '{print $1}' file.txt

# Вывести первую и третью колонки
awk '{print $1, $3}' file.txt

# Вывести последнюю колонку
awk '{print $NF}' file.txt

# Указать разделитель (например, для CSV)
awk -F',' '{print $1, $3}' data.csv

# Для /etc/passwd (разделитель :)
awk -F':' '{print $1, $6}' /etc/passwd

Условия и фильтрация

Пример
# Строки, где третье поле больше 100
awk '$3 > 100' data.txt

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

# Строки, где первое поле равно "admin"
awk '$1 == "admin"' users.txt

# Комбинация условий
awk '$3 > 50 && $4 == "active"' data.txt

# Строки длиннее 80 символов
awk 'length > 80' file.txt

Форматированный вывод (printf)

Пример
# Форматированный вывод
awk '{printf "%-20s %10d\n", $1, $3}' data.txt

# Вывод с заголовком
awk 'BEGIN {printf "%-15s %s\n", "Name", "Size"} {printf "%-15s %d\n", $1, $5}' <(ls -l)

Блоки BEGIN и END

Пример
# Подсчитать сумму значений в третьем поле
awk '{sum += $3} END {print "Total:", sum}' data.txt

# Среднее значение
awk '{sum += $3; count++} END {print "Average:", sum/count}' data.txt

# Заголовок + итог
awk 'BEGIN {print "=== Report ==="} {print $0} END {print "Lines:", NR}' file.txt

Практические примеры

Пример
# Анализ использования диска (топ-5 по размеру)
du -sh /var/log/* | sort -rh | head -5

# Вывести PID и имя Java-процессов
ps aux | awk '/[j]ava/ {print $2, $11}'

# Суммировать размер файлов определённого типа
find . -name "*.jar" -ls | awk '{total += $7} END {printf "Total: %.2f MB\n", total/1024/1024}'

# Разбор CSV с заголовком
awk -F',' 'NR==1 {for(i=1;i<=NF;i++) header[i]=$i; next} {print header[1]"="$1, header[3]"="$3}' data.csv

# Подсчёт запросов по HTTP-статусу из access.log
awk '{print $9}' access.log | sort | uniq -c | sort -rn

На собеседовании: интервьюер ожидает умение извлекать нужные колонки ($1, $NF), использовать -F для указания разделителя и знать про блоки BEGIN/END. Частая ошибка — не знать про $NF (последнее поле) и пытаться считать колонки вручную.