Команда awk в Linux

awk

Среди многочисленных инструментов обработки текста, доступных в оболочке Linux, awk выделяется своей мощью и универсальностью. Разработанный в 1970-х годах Ахо, Вайнбергером и Керниганом, awk — это больше, чем просто команда, это незаменимый инструмент в арсенале системного администратора и DevOps инженера. Она позволяет за секунды решать задачи которые потребовали бы десятков строк кода на других языках, это полноценный язык программирования, предназначенный для обработки и анализа текстовых файлов.

Основные преимущества awk: работа со структурированными данными по столбцам, встроенная поддержка регулярных выражений, математические вычисления, минималистичный синтаксис для простых задач и возможность создания сложных программ для продвинутых сценариев.

Изучив базовые концепции из этого руководства вы сможете: анализировать лог-файлы веб-серверов и приложений, обрабатывать CSV и другие табличные данные, автоматизировать рутинные операции с текстом, мониторить системные ресурсы и строить отчеты.

Команда awk

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

Основной синтаксис

Основной синтаксис awk следующий:

awk ‘pattern {action}’ file

  • Шаблон: Указывает, когда должно быть выполнено действие. Если это значение опущено, действие применяется к каждой строке.
  • Действие: Набор команд, выполняемых при совпадении с шаблоном. Действия заключаются в фигурные скобки {}.

Базовая структура:

awk 'pattern {action}' файл
  • pattern — условие отбора строк (опционально)
  • action — действие над строками которые соответствуют условию
  • файл — входной файл (можно несколько или stdin через pipe)

Примеры awk

Основные варианты использования:

Печать всех строк (как 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

Сумма и среднее значение столбца

awk ‘{sum+=$2; count++} END {print «Sum =», sum; print «Average =», sum/count}’ file.txt

Эта команда вычисляет сумму и среднее значение значений во втором столбце файла file.txt.

Фильтрация на основе условия

awk ‘$3 > 100’ file.txt

Здесь отображаются строки из файла file.txt, в которых третье поле больше 100.

 

Важные опции командной строки:

ОпцияОписаниеПример
-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

Запись (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 — выполняется один раз после обработки всех данных

Заголовок и итог

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 предоставляет набор предопределенных переменных для работы с данными.

ПеременнаяОписаниеПример использования
NRNumber of Records — номер текущей строки{print NR, $0}
NFNumber of Fields — количество полей в строке{print $NF} (последнее поле)
FSField Separator — разделитель входных полейBEGIN {FS=":"} {print $1}
OFSOutput Field Separator — разделитель выходных полейBEGIN {OFS=","} {print $1, $2}
RSRecord Separator — разделитель входных записейBEGIN {RS=";"} {print}
ORSOutput 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 '{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 '{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 (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

Выравнивание столбцов

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 лучше для:

  • Работы со столбцами данных
  • Математических вычислений
  • Сложной логики (условия, циклы)
  • Создания отчетов

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 преимущества:

  • Быстрее для простых задач (нет накладных расходов на интерпретатор)
  • Короче код для типичных операций
  • Встроен в любой 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

Ошибка — поле «New York» разбивается на два

awk -F',' '{print $3}' cities.csv

Решение — обрезка пробелов

awk -F',' '{gsub(/^ +| +$/, "", $3); print $3}' cities.csv

Как вывести последнюю колонку?

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 --version

или

which awk

Основные реализации:

  • gawk — GNU Awk, самая распространенная в Linux
  • mawk — быстрая реализация, меньше функций
  • nawk — «new awk», стандарт POSIX
  • оригинальный awk — устаревший, в современных системах обычно это симлинк на gawk

Часто задаваемые вопросы

Как изменить разделитель полей в awk?

Используйте опцию -F, за которой следует нужный разделитель. Например, awk -F, ‘{print $2}’ file.csv выведет второе поле CSV-файла.

Может ли awk обрабатывать несколько файлов одновременно?

Да, awk может обрабатывать несколько файлов последовательно. Используйте awk ‘{print}’ file1.txt file2.txt для последовательной обработки файлов file1.txt и file2.txt.

Как интегрировать awk с переменными оболочки?

Вы можете передавать переменные оболочки в awk с помощью опции -v. Например, var=»value»; awk -v awkVar=»$var» ‘{print awkVar}’ file.txt выведет значение переменной оболочки var для каждой строки в file.txt.

Можно ли модифицировать файл на месте с помощью awk?

Нет, awk не поддерживает прямое редактирование на месте, как sed -i. Однако вы можете добиться этого, перенаправив вывод awk во временный файл, а затем переименовав его в исходный файл.

Можно ли использовать awk для сложной обработки текста?

Безусловно. Несмотря на то, что awk прост для выполнения базовых задач, он достаточно мощный для сложной обработки текста. Он поддерживает массивы, функции и регулярные выражения, что делает его подходящим для различных задач по работе с текстом.

Заключение

Команда awk — это универсальный инструмент командной строки для обработки текста в системах на базе Unix. Ее простые и в то же время надежные функции делают ее незаменимым инструментом для всех, кто имеет дело с текстовыми файлами — от анализа журналов до извлечения данных. Освоив awk, пользователи смогут использовать весь потенциал работы с текстом в Linux.