Когда нужно быстро извлечь третий столбец из лог-файла на 100,000 строк, подсчитать сумму чисел в CSV или найти дубликаты в конфигурационных файлах, опытные системные администраторы тянутся к одному инструменту — awk. Эта утилита командной строки существует с 1977 года, но до сих пор остается незаменимой для обработки структурированного текста.
В отличие от Python скриптов которые нужно писать и отлаживать, awk позволяет решать большинство задач обработки текста одной строкой кода. В отличие от grep который просто ищет паттерны, awk анализирует структуру данных по столбцам и строкам, выполняет математические вычисления и форматирует вывод.
В этом руководстве покажем как использовать awk для повседневных задач системного администратора: анализ логов веб-сервера, обработка CSV файлов, мониторинг системных ресурсов и автоматизация рутинных операций. Все примеры протестированы на реальных серверах THE.Hosting и готовы к использованию.
Что такое awk и зачем он нужен
AWK — это язык программирования и утилита командной строки для обработки текстовых данных в Unix и Linux системах. Название происходит от фамилий создателей: Aho, Weinberger и Kernighan, которые разработали язык в Bell Labs в 1977 году.
Основная концепция awk: программа читает входной текст построчно, разбивает каждую строку на поля (столбцы) по разделителю и выполняет указанные действия над этими полями. Это делает awk идеальным для работы со структурированными данными — логами, CSV файлами, выводом системных команд, конфигурационными файлами.
Когда использовать awk:
- Извлечение конкретных столбцов из таблиц данных
- Фильтрация строк по условиям (больше/меньше, содержит текст)
- Вычисления по столбцам (сумма, среднее, подсчет)
- Форматирование вывода других команд
- Обработка CSV, TSV, лог-файлов
- Быстрый анализ больших текстовых файлов без загрузки в память
Сравнение с альтернативами:
| Инструмент | Когда использовать | Сложность |
|---|---|---|
| awk | Работа со столбцами, вычисления, форматирование | Средняя |
| grep | Простой поиск строк по паттерну | Низкая |
| sed | Замена текста, редактирование потока | Средняя |
| cut | Извлечение фиксированных столбцов | Низкая |
| Python | Сложная логика, большие проекты | Высокая |
Реальный пример: У вас есть лог веб-сервера с 50,000 строк. Нужно найти все запросы к API эндпоинту /api/users и посчитать сколько раз каждый IP адрес обращался. С awk это одна строка:
awk '/\/api\/users/ {count[$1]++} END {for (ip in count) print ip, count[ip]}' access.log
Эквивалентный Python скрипт занял бы 15-20 строк кода.
Синтаксис команды awk
Базовая структура:
awk 'pattern {action}' файл
- pattern — условие отбора строк (опционально)
- action — действие над строками которые соответствуют условию
- файл — входной файл (можно несколько или stdin через pipe)
Основные варианты использования:
Печать всех строк (как cat):
awk '{print}' file.txt
Печать первого столбца:
awk '{print $1}' file.txt
Строки содержащие "error":
awk '/error/ {print}' file.txt
С условием на значение столбца:
awk '$3 > 100 {print $1, $3}' file.txt
Несколько действий через точку с запятой:
awk '{sum += $2; count++} END {print sum/count}' file.txt
Важные опции командной строки:
| Опция | Описание | Пример |
|---|---|---|
-F |
Указать разделитель полей | awk -F':' '{print $1}' /etc/passwd |
-v |
Передать переменную в программу | awk -v limit=100 '$3 > limit' |
-f |
Читать программу из файла | awk -f script.awk data.txt |
Разделители полей:
По умолчанию awk разбивает строки по пробелам и табуляциям. Для других разделителей:
CSV файл (запятая):
awk -F',' '{print $1, $3}' data.csv
Файл /etc/passwd (двоеточие):
awk -F':' '{print $1, $6}' /etc/passwd
Несколько символов разделителей:
awk -F'[,:]' '{print $1}' mixed.txt
Регулярное выражение как разделитель:
awk -F'[[:space:]]+' '{print $1}' file.txt
Базовые концепции awk
Поля и записи
Запись (Record) — строка входного текста. Awk обрабатывает файл построчно.
Поле (Field) — столбец в записи, разделенный специальным символом.
Обозначение полей:
$0— вся строка целиком$1— первое поле (первый столбец)$2— второе поле$NF— последнее поле (NF= number of fields)$(NF-1)— предпоследнее поле
Пример данных (employees.txt):
John Manager Sales 5000
Alice Developer IT 6000
Bob Analyst Finance 4500
Работа с полями:
Печать имени и зарплаты
awk '{print $1, $4}' employees.txt
Переставить столбцы местами
awk '{print $4, $2, $1}' employees.txt
Конкатенация строк
awk '{print $1 " работает в " $3}' employees.txt
Арифметика
awk '{print $1, $4 * 1.15}' employees.txt
Паттерны (условия)
Паттерны определяют какие строки обрабатывать.
Типы паттернов:
1. Регулярные выражения (между слэшами):
Печатает строки содержащие "IT":
awk '/IT/ {print}' employees.txt
2. Сравнение полей:
Печатает сотрудников с зарплатой > 5000:
awk '$4 > 5000 {print $1, $4}' employees.txt
3. Логические операторы:
Оператор И (AND) — отдел Sales И зарплата > 4000:
awk '$3 == "Sales" && $4 > 4000 {print}' employees.txt
Оператор ИЛИ (OR) — зарплата < 5000 ИЛИ должность Manager:
awk '$4 < 5000 || $2 == "Manager" {print}' employees.txt
4. Диапазоны строк:
Печатает строки от паттерна START до END включительно:
awk '/START/,/END/ {print}' file.txt
5. Отрицание:
Все кроме отдела IT:
awk '$3 != "IT" {print}' employees.txt
Строки НЕ содержащие Manager:
awk '!/Manager/ {print}' employees.txt
Операторы сравнения:
| Оператор | Значение | Пример |
|---|---|---|
== |
Равно | $1 == "John" |
!= |
Не равно | $2 != "Sales" |
< |
Меньше | $3 < 100 |
> |
Больше | $3 > 1000 |
<= |
Меньше или равно | $3 <= 50 |
>= |
Больше или равно | $3 >= 100 |
~ |
Соответствует regex | $1 ~ /^A/ |
!~ |
Не соответствует regex | $1 !~ /test/ |
Специальные паттерны BEGIN и END
BEGIN — выполняется один раз перед обработкой данных
END — выполняется один раз после обработки всех данных
Заголовок и итог
awk 'BEGIN {print "Имя\tЗарплата"}
{print $1, $4}
END {print "---\nВсего сотрудников:", NR}' employees.txt
Практический пример — вычисление среднего:
awk 'BEGIN {sum=0; count=0}
{sum += $4; count++}
END {print "Средняя зарплата:", sum/count}' employees.txt
Встроенные переменные awk
Awk предоставляет набор предопределенных переменных для работы с данными.
| Переменная | Описание | Пример использования |
|---|---|---|
NR |
Number of Records — номер текущей строки | {print NR, $0} |
NF |
Number of Fields — количество полей в строке | {print $NF} (последнее поле) |
FS |
Field Separator — разделитель входных полей | BEGIN {FS=":"} {print $1} |
OFS |
Output Field Separator — разделитель выходных полей | BEGIN {OFS=","} {print $1, $2} |
RS |
Record Separator — разделитель входных записей | BEGIN {RS=";"} {print} |
ORS |
Output Record Separator — разделитель выходных записей | BEGIN {ORS="---\n"} {print} |
FILENAME |
Имя текущего обрабатываемого файла | {print FILENAME, $0} |
FNR |
Номер строки в текущем файле | {print FILENAME, FNR, $0} |
Примеры использования:
Нумерация строк
awk '{print NR, $0}' file.txt
Вывод количества полей в каждой строке
awk '{print "Строка", NR, "содержит", NF, "полей"}' data.txt
Изменение разделителя вывода
awk 'BEGIN {OFS=" | "} {print $1, $2, $3}' file.txt
Обработка нескольких файлов
awk '{print FILENAME, FNR, $1}' file1.txt file2.txt
Операции и вычисления в awk
Арифметические операции
Базовые операции: + - * / % (остаток от деления)
awk '{print $1, $2 * 1.2}' file.txt
Увеличение значения
awk '{$4 = $4 * 1.15; print}' employees.txt
Накопление суммы
awk '{sum += $3} END {print "Итого:", sum}' sales.txt
Счетчик
awk '/error/ {count++} END {print "Ошибок:", count}' log.txt
Строковые операции
Конкатенация строк (просто пробел)
awk '{print $1 $2}' file.txt # JohnDoe
awk '{print $1 " " $2}' file.txt # John Doe
awk '{print $1 "-" $2}' file.txt # John-Doe
Функция length() — длина строки
awk '{print $1, length($1)}' file.txt
awk 'length($0) > 80 {print}' file.txt # Строки длиннее 80 символов
Функция substr() — подстрока
awk '{print substr($1, 1, 3)}' file.txt # Первые 3 символа
Функция tolower() и toupper()
awk '{print tolower($1)}' file.txt
awk '{print toupper($1)}' file.txt
Функция gsub() — замена всех вхождений
awk '{gsub(/old/, "new"); print}' file.txt
Функция sub() — замена первого вхождения
awk '{sub(/old/, "new"); print}' file.txt
Функция match() — поиск паттерна
awk 'match($0, /[0-9]+/) {print substr($0, RSTART, RLENGTH)}' file.txt
Условные конструкции
If-else:
Базовый if
awk '{if ($3 > 5000) print $1, "высокая зарплата"}' employees.txt
If-else
awk '{if ($4 > 5000)
print $1, "высокая"
else
print $1, "низкая"}' employees.txt
Многострочная программа
awk '{
if ($4 >= 6000)
category = "senior"
else if ($4 >= 5000)
category = "middle"
else
category = "junior"
print $1, category
}' employees.txt
Тернарный оператор:
awk '{print $1, ($4 > 5000 ? "high" : "low")}' employees.txt
Циклы
For цикл:
Вывод всех полей построчно
awk '{for (i=1; i<=NF; i++) print i, $i}' file.txt
Сумма всех чисел в строке
awk '{sum=0; for(i=1; i<=NF; i++) sum+=$i; print sum}' numbers.txt
While цикл:
awk '{i=1; while(i<=NF) {print i":"$i; i++}}' file.txt
Массивы в awk
Массивы в awk ассоциативные (как хеш-таблицы) — ключом может быть любая строка.
Базовое использование массивов
Подсчет уникальных значений
awk '{count[$1]++} END {for (name in count) print name, count[name]}' file.txt
Суммирование по категориям
awk '{sales[$3] += $4}
END {for (dept in sales) print dept, sales[dept]}' data.txt
Практические примеры с массивами
Подсчет IP адресов в логе:
awk '{ip_count[$1]++}
END {for (ip in ip_count) print ip, ip_count[ip]}' access.log | sort -rn -k2
Группировка по статусам HTTP:
awk '{status[$9]++}
END {for (code in status) print code, status[code]}' access.log
Нахождение дубликатов:
awk '{if (seen[$0]++) print "Дубликат:", $0}' file.txt
Удаление дубликатов (вывод уникальных строк):
awk '!seen[$0]++' file.txt
Практические примеры для реальных задач
Анализ логов веб-сервера
Формат access.log:
192.168.1.100 - - [24/Feb/2026:10:15:30 +0000] "GET /index.html HTTP/1.1" 200 1234
Топ-10 IP адресов по количеству запросов:
awk '{ip[$1]++} END {for (i in ip) print ip[i], i}' access.log | sort -rn | head -10
Подсчет запросов по HTTP методам:
awk '{print $6}' access.log | sort | uniq -c
Фильтрация ошибок 404:
awk '$9 == 404 {print $7}' access.log | sort | uniq -c | sort -rn
Трафик по часам:
awk '{print substr($4, 14, 2)}' access.log | sort | uniq -c
Обработка CSV файлов
Пример CSV (sales.csv):
Date,Product,Quantity,Price
2026-02-01,Widget,10,25.50
2026-02-01,Gadget,5,120.00
2026-02-02,Widget,8,25.50
Вычисление общей выручки:
awk -F',' 'NR>1 {sum += $3 * $4} END {print "Total:", sum}' sales.csv
Сумма по продуктам:
awk -F',' 'NR>1 {total[$2] += $3 * $4}
END {for (p in total) print p, total[p]}' sales.csv
Фильтрация по дате:
awk -F',' '$1 ~ /2026-02-01/ {print $2, $3}' sales.csv
Форматированный вывод с заголовками:
awk -F',' 'BEGIN {print "Product | Total"}
NR>1 {total[$2] += $3 * $4}
END {for (p in total) printf "%-10s | $%.2f\n", p, total[p]}' sales.csv
Системное администрирование
Мониторинг использования диска:
df -h | awk 'NR>1 {if ($5+0 > 80) print $6, "занято", $5}'
Топ процессов по памяти:
ps aux | awk 'NR>1 {print $11, $4"%"}' | sort -k2 -rn | head -10
Анализ активных соединений:
netstat -an | awk '/ESTABLISHED/ {count[$5]++}
END {for (ip in count) print ip, count[ip]}' | sort -rn -k2
Проверка открытых портов:
netstat -tuln | awk 'NR>2 {print $4}' | awk -F':' '{print $NF}' | sort -n | uniq
Обработка конфигурационных файлов
Извлечение активных пользователей из /etc/passwd:
awk -F':' '$7 !~ /nologin|false/ {print $1, $6}' /etc/passwd
Пользователи с UID > 1000:
awk -F':' '$3 >= 1000 {print $1, $3}' /etc/passwd
Группы пользователя:
awk -F':' '/^username:/ {print $4}' /etc/passwd |
xargs -I {} awk -F':' '$3 == {} {print $1}' /etc/group
Продвинутые техники
Многофайловая обработка
Сравнение двух файлов
awk 'NR==FNR {a[$1]; next} $1 in a' file1.txt file2.txt
Разница файлов
awk 'NR==FNR {a[$1]; next} !($1 in a)' file1.txt file2.txt
Форматирование вывода с printf
Выравнивание столбцов
awk '{printf "%-10s %8.2f\n", $1, $2}' file.txt
Таблица с заголовками
awk 'BEGIN {printf "%-10s %10s %10s\n", "Name", "Salary", "Dept"}
{printf "%-10s %10d %10s\n", $1, $4, $3}' employees.txt
Вызов внешних команд
Выполнение shell команды
awk '{system("echo Processing: " $1)}' file.txt
Чтение вывода команды
awk 'BEGIN {
cmd = "date"
cmd | getline result
close(cmd)
print result
}'
Создание отчетов
Подробный отчет по логам:
awk 'BEGIN {
print "=== Web Server Report ==="
print "Generated:", strftime("%Y-%m-%d %H:%M:%S")
}
{
requests++
bytes += $10
status[$9]++
if ($9 >= 400) errors++
}
END {
print "\nTotal Requests:", requests
print "Total Traffic:", bytes/1024/1024, "MB"
print "Error Rate:", (errors/requests)*100 "%"
print "\nStatus Codes:"
for (code in status)
printf " %s: %d (%.1f%%)\n", code, status[code], (status[code]/requests)*100
}' access.log
Сравнение awk с альтернативами
awk vs sed
awk лучше для:
- Работы со столбцами данных
- Математических вычислений
- Сложной логики (условия, циклы)
- Создания отчетов
sed лучше для:
- Простой замены текста
- Редактирования потока
- Удаления строк
- Вставки текста
Пример задачи: Извлечь email адреса из текста
awk
awk 'match($0, /[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}/) {
print substr($0, RSTART, RLENGTH)
}' file.txt
sed (сложнее и менее читабельно)
sed -n 's/.*\([a-zA-Z0-9._-]\+@[a-zA-Z0-9._-]\+\.[a-zA-Z]\{2,\}\).*/\1/p' file.txt
awk vs Python
awk преимущества:
- Быстрее для простых задач (нет накладных расходов на интерпретатор)
- Короче код для типичных операций
- Встроен в любой Linux
- Удобнее в pipe цепочках
Python преимущества:
- Больше возможностей стандартной библиотеки
- Лучше для сложной логики
- Проще отладка
- Больше документации
Сравнение кода — подсчет средней зарплаты:
awk (1 строка)
awk '{sum+=$4; count++} END {print sum/count}' employees.txt
Python (минимум 7 строк)
with open('employees.txt') as f:
total = 0
count = 0
for line in f:
salary = int(line.split()[3])
total += salary
count += 1
print(total / count)
Оптимизация и лучшие практики
Производительность
1. Избегайте ненужных операций:
Плохо - проверка на каждой строке
awk '{if (NR > 1) print}' file.txt
Хорошо - используйте диапазон
awk 'NR > 1' file.txt
2. Используйте встроенные переменные:
Медленно
awk '{print $1, $2, $3, $4}' file.txt
Быстрее
awk '{$5=""; print}' file.txt
3. Фильтруйте рано:
Плохо - обрабатывает все строки
awk '{sum += $3} $2 == "Sales" {print}' file.txt
Хорошо - фильтрует сразу
awk '$2 == "Sales" {sum += $3; print}' file.txt
Читабельность кода
Используйте переменные:
Плохо
awk '$3 > 5000 && $4 == "IT" {print $1}' file.txt
Хорошо
awk '{
salary = $3
dept = $4
name = $1
if (salary > 5000 && dept == "IT")
print name
}' file.txt
Выносите сложные программы в файлы:
script.awk
BEGIN {
FS = ","
OFS = " | "
total = 0
}
NR > 1 {
total += $3 * $4
printf "%s | %s | %.2f\n", $1, $2, $3 * $4
}
END {
print "---"
printf "Total: $%.2f\n", total
}
Использование:
awk -f script.awk data.csv
Распространенные ошибки и решения
Проблема: Неправильный разделитель полей
Ошибка - CSV обрабатывается как пробелы
awk '{print $2}' data.csv
Решение - указать разделитель
awk -F',' '{print $2}' data.csv
Проблема: Пропуск заголовка
Ошибка - заголовок участвует в вычислениях
awk '{sum += $2} END {print sum}' file.csv
Решение 1 - начать со второй строки
awk 'NR > 1 {sum += $2} END {print sum}' file.csv
Решение 2 - пропустить нечисловые
awk '{if ($2 ~ /^[0-9]+$/) sum += $2} END {print sum}' file.csv
Проблема: Деление на ноль
Ошибка - возможно деление на ноль
awk '{print $1 / $2}' file.txt
Решение - проверка
awk '{if ($2 != 0) print $1 / $2; else print "N/A"}' file.txt
Проблема: Пробелы в полях CSV
Ошибка - поле "New York" разбивается на два
awk -F',' '{print $3}' cities.csv
Решение - обрезка пробелов
awk -F',' '{gsub(/^ +| +$/, "", $3); print $3}' cities.csv
Частые вопросы (FAQ)
Как вывести последнюю колонку?
awk '{print $NF}' file.txt
Как вывести все кроме первой колонки?
awk '{$1=""; print}' file.txt
Или чище:
awk '{for(i=2;i<=NF;i++) printf "%s ", $i; print ""}' file.txt
Как подсчитать количество строк?
awk 'END {print NR}' file.txt
Или просто
wc -l file.txt
Как обработать файлы с путями содержащими пробелы?
Используйте переменную FILENAME
awk '{print FILENAME, $0}' "file with spaces.txt"
Как вывести строки между двумя паттернами?
awk '/START/,/END/' file.txt
Как удалить дубликаты сохранив порядок?
awk '!seen[$0]++' file.txt
Можно ли изменить исходный файл?
Нет, awk только читает. Для записи:
awk '{print $1, $2}' input.txt > output.txt
Как обработать JSON в awk?
Awk плохо подходит для JSON. Используйте jq:
jq '.items[] | .name' file.json
Установка и версии awk
Проверка установленной версии:
awk --version
или
which awk
Основные реализации:
- gawk — GNU Awk, самая распространенная в Linux
- mawk — быстрая реализация, меньше функций
- nawk — "new awk", стандарт POSIX
- оригинальный awk — устаревший, в современных системах обычно это симлинк на gawk
Установка на разных системах:
Ubuntu/Debian
sudo apt install gawk
CentOS/RHEL
sudo yum install gawk
macOS
brew install gawk
На серверах THE.Hosting gawk предустановлен на всех тарифах и готов к использованию.
Заключение
Команда awk — незаменимый инструмент в арсенале системного администратора и DevOps инженера. Она позволяет за секунды решать задачи которые потребовали бы десятков строк кода на других языках.
Основные преимущества awk: работа со структурированными данными по столбцам, встроенная поддержка регулярных выражений, математические вычисления, минималистичный синтаксис для простых задач и возможность создания сложных программ для продвинутых сценариев.
Изучив базовые концепции из этого руководства вы сможете: анализировать лог-файлы веб-серверов и приложений, обрабатывать CSV и другие табличные данные, автоматизировать рутинные операции с текстом, мониторить системные ресурсы и строить отчеты.
На серверах THE.Hosting вы можете использовать awk для анализа логов веб-сервера, мониторинга нагрузки и автоматизации задач администрирования. Все современные дистрибутивы Linux на наших VPS включают GNU Awk готовый к работе.
Заказать VPS для работы с Linux
Дополнительные ресурсы:
- GNU Awk Manual — официальная документация
- The AWK Programming Language — книга создателей языка
- Awk One-Liners — коллекция готовых решений