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(последнее поле) и пытаться считать колонки вручную.