Инструкция

grep, sed и awk: примеры обработки текста в терминале Linux

Обновлено: · Skillaria.Top

grep находит строки по шаблону (grep -rn error /var/log), sed изменяет текст в потоке или в файле (sed -i 's/old/new/g' file), а awk работает с колонками и считает (awk '{print $1}' access.log). Вместе в конвейере они заменяют скрипт: grep фильтрует строки, sed правит текст, awk вырезает поля и агрегирует.

grep, sed и awk — три классические утилиты Linux для обработки текста. grep находит строки по шаблону, sed заменяет и удаляет текст в потоке, не открывая редактор, а awk разбивает строку на колонки и умеет считать. Ниже — grep sed awk примеры, которые реально нужны при разборе логов, конфигов и вывода команд, плюс типичные ошибки.

Когда что использовать

Все три инструмента читают текст построчно и пишут результат в стандартный вывод, поэтому их легко соединять через |. Разница — в задаче, которую каждый решает лучше всего.

ЗадачаИнструментПример
Найти строки с текстомgrepgrep ERROR app.log
Заменить текстsedsed 's/http:/https:/g' file
Удалить или показать строки по номеруsedsed -n '10,20p' file
Достать колонкуawkawk '{print $1}' access.log
Посчитать сумму, среднее, группировкуawkawk '{s+=$10} END {print s}'

Простое правило: если нужно только отфильтровать — берите grep, если изменить текст — sed, если в тексте есть колонки или нужна арифметика — awk.

grep: поиск строк по шаблону

Базовые примеры grep

# Строки со словом error в файле
grep error /var/log/syslog

# Без учёта регистра: Error, ERROR, error
grep -i error app.log

# С номерами строк
grep -n "Connection refused" app.log

# Рекурсивно по каталогу, с именами файлов
grep -rn "DB_HOST" /etc/myapp/

# Только имена файлов, где есть совпадение
grep -rl "TODO" src/

# Инвертировать: всё, КРОМЕ комментариев и пустых строк
grep -v -e '^#' -e '^$' /etc/ssh/sshd_config

# Посчитать число совпавших строк
grep -c " 500 " access.log

Флаг -w ищет слово целиком: grep -w log не найдёт login. Флаг -F отключает регулярные выражения и ищет строку буквально — удобно, когда в шаблоне есть точки, скобки или звёздочки.

Контекст вокруг найденной строки

Ошибка в логе редко понятна по одной строке — нужен стек или запрос, который к ней привёл. Для этого есть флаги контекста:

# 3 строки после совпадения (After)
grep -A 3 "Traceback" app.log

# 2 строки до (Before)
grep -B 2 "OOM" /var/log/kern.log

# по 5 строк с обеих сторон (Context)
grep -C 5 "segfault" /var/log/syslog

Группы совпадений grep разделяет строкой --, так что вывод легко читать глазами.

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

По умолчанию grep понимает базовые регулярки (BRE). С флагом -E включаются расширенные (ERE), где +, ?, | и скобки работают без обратных слэшей.

КонструкцияЗначениеПример
^начало строкиgrep '^root' /etc/passwd
$конец строкиgrep 'bash$' /etc/passwd
.любой символgrep 'h.t'
*0 и более повторенийgrep 'ab*c'
+ (ERE)1 и болееgrep -E '[0-9]+'
| (ERE)илиgrep -E 'error|warn'
[...]один символ из набораgrep '[Ee]rror'
# Строки с ошибками или предупреждениями
grep -E "ERROR|WARN" app.log

# Только IP-адреса из лога, по одному на строку (-o — печатать лишь совпадение)
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' access.log

grep -P: вытащить значение между известными кусками

В GNU grep есть флаг -P — регулярки в стиле Perl. С ним доступны \K («забыть всё, что совпало до этого места») и просмотр вперёд, что позволяет вытащить только значение:

$ echo 'user_id=4821 status=ok' | grep -oP 'user_id=\K[0-9]+'
4821

$ grep -oP '"version":\s*"\K[^"]+' package.json
2.4.1

Флаг -P есть не во всех сборках grep (например, в BSD grep на macOS его нет), поэтому в переносимых скриптах лучше использовать sed или awk.

grep -q в условиях скриптов

grep -q ничего не печатает и только возвращает код выхода: 0 — найдено, 1 — нет. Так проверку можно записать прямо в if:

if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
  echo "root-вход отключён"
fi

Это короче, чем сохранять вывод в переменную и проверять её на пустоту, и grep останавливается на первом совпадении.

sed: замена и удаление текста

Замена: команда s

Основная команда sed — s/шаблон/замена/флаги. Без флага g заменяется только первое совпадение в каждой строке.

# Вывести текст с заменой (файл не меняется)
sed 's/foo/bar/' file.txt

# Заменить все вхождения в строке
sed 's/foo/bar/g' file.txt

# Без учёта регистра (GNU sed)
sed 's/error/ERROR/gI' app.log

# Другой разделитель, если в тексте есть слэши
sed 's|/var/www|/srv/www|g' nginx.conf

sed -i: замена прямо в файле

Флаг -i записывает результат обратно в файл. Чтобы не потерять исходник, задайте суффикс резервной копии:

# Создаст config.ini.bak и изменит config.ini
sed -i.bak 's/^debug=true/debug=false/' config.ini

# Замена во всех .conf в каталоге
find /etc/myapp -name "*.conf" -exec sed -i 's/old-host/new-host/g' {} +

Перед массовой правкой сначала запустите команду без -i и посмотрите на вывод. На macOS (BSD sed) у -i обязательный аргумент: sed -i '' 's/a/b/' file.

Работа со строками по номеру и по шаблону

# Показать строки 10–20 (-n отключает автопечать, p — печать)
sed -n '10,20p' file.txt

# Удалить строку 5
sed '5d' file.txt

# Удалить последнюю строку
sed '$d' file.txt

# Удалить пустые строки и комментарии
sed -e '/^$/d' -e '/^#/d' nginx.conf

# Заменить только в строках, где есть "listen"
sed '/listen/s/80/8080/' nginx.conf

# Вставить строку после совпадения (GNU sed)
sed '/^\[mysqld\]/a max_connections = 500' my.cnf

Обратные ссылки и &

Часть шаблона в скобках можно подставить в замену через \1, \2, а символ & означает весь найденный текст.

# Поменять местами имя и фамилию (ERE через -E)
$ echo "Иванов Пётр" | sed -E 's/(\S+) (\S+)/\2 \1/'
Пётр Иванов

# Обернуть все числа в квадратные скобки
$ echo "port 8080, timeout 30" | sed -E 's/[0-9]+/[&]/g'
port [8080], timeout [30]

# Дату 2026-10-14 превратить в 14.10.2026
$ echo 2026-10-14 | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/'
14.10.2026

awk: колонки, условия и подсчёты

Вывод нужного столбца

awk делит каждую строку на поля по пробелам и табуляциям: $1 — первое поле, $2 — второе, $NF — последнее, $0 — вся строка.

# IP-адреса из лога nginx (первая колонка)
awk '{print $1}' /var/log/nginx/access.log

# Имя пользователя и shell из /etc/passwd (разделитель — двоеточие)
awk -F: '{print $1, $7}' /etc/passwd

# Последняя колонка
df -h | awk '{print $NF}'

# Свой разделитель при выводе
awk -F: -v OFS=';' '{print $1, $3}' /etc/passwd

Условия: печатать только нужные строки

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

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

# Запросы с кодом ответа 500 и выше (9-е поле в формате combined)
awk '$9 >= 500' access.log

# Строки, где 6-я колонка совпадает с регуляркой
awk '$6 ~ /POST/' access.log

# Файлы больше 100 МБ из вывода ls -l
ls -l | awk '$5 > 100*1024*1024 {print $9}'

BEGIN, END и NR: awk как маленькая программа

Блок BEGIN выполняется до чтения первой строки, END — после последней. NR хранит номер текущей строки, а в блоке END — общее их число.

# Сумма размеров ответов (10-е поле) в мегабайтах
awk '{sum += $10} END {printf "%.1f MB\n", sum/1024/1024}' access.log

# Среднее время ответа из последней колонки
awk '{s += $NF} END {if (NR) print s/NR}' timings.log

# Пропустить заголовок CSV
awk -F, 'NR > 1 {print $2}' users.csv

# Подсчёт запросов по IP: ассоциативный массив
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head

Последний пример — классика разбора логов: массив count с ключом-IP заменяет связку sort | uniq -c и легко расширяется, например до суммы трафика по каждому адресу.

Конвейеры: grep, sed и awk вместе

Настоящая сила — в комбинации. Каждый инструмент делает свою часть, а | передаёт результат дальше.

Топ-10 IP с ошибками 5xx

grep ' 50[0-9] ' /var/log/nginx/access.log \
  | awk '{print $1}' \
  | sort | uniq -c | sort -rn | head -10
    412 203.0.113.45
    118 198.51.100.7
     36 192.0.2.19

Здесь grep грубо отсекает строки, awk вырезает поле, а sort | uniq -c считает повторы. Это можно записать и одним awk: awk '$9 ~ /^5/ {c[$1]++} END {for (i in c) print c[i], i}' access.log | sort -rn | head — так точнее, потому что проверяется именно колонка кода ответа.

Какие URL открывают чаще всего

awk '{print $7}' access.log | sed 's/?.*//' | sort | uniq -c | sort -rn | head

sed здесь отрезает query-строку, чтобы /search?q=a и /search?q=b считались одной страницей.

Значения из конфига без комментариев

grep -v '^\s*#' /etc/myapp/app.env | grep '=' | awk -F= '{print $1}'

Ошибки за конкретный час

grep '14/Oct/2026:03:' access.log | awk '$9 >= 500 {print $4, $7, $9}'

Типичные ошибки

  • Двойные кавычки вместо одинарных в awk. В awk "{print $1}" shell подставит свою переменную $1 до запуска awk. Программу awk и выражения sed пишите в одинарных кавычках.
  • Забыли g в sed. Без него заменяется только первое совпадение в строке, остальные остаются.
  • sed -i без проверки. Неудачная регулярка молча испортит файл. Сначала прогоните без -i или используйте -i.bak.
  • + и | не работают в grep. Это расширенный синтаксис: нужен grep -E (или sed -E).
  • Точка в шаблоне. grep 192.168.1.1 найдёт и 192x168y1z1: точка — это «любой символ». Используйте grep -F или экранируйте \..
  • Пробелы в колонках. Если поле может содержать пробелы (CSV, путь), задайте разделитель явно: awk -F, или awk -F'\t'.
  • Бесполезный cat. cat file | grep x работает, но grep x file короче и не порождает лишний процесс.

Чем заменить grep, sed и awk

Для JSON эти утилиты неудобны: структуру лучше разбирать jq (jq '.items[] | select(.status=="active") | .name'), а YAML — yq. Для быстрого рекурсивного поиска по большим проектам часто используют ripgrep (команда rg), который по умолчанию учитывает .gitignore. Если привычнее синтаксис Perl, perl -pe 's/a/b/g' и perl -lane 'print $F[0]' заменяют sed и awk одной строкой. Но grep, sed и awk есть практически на любом сервере без установки — поэтому их стоит знать в первую очередь.

Итог

grep ищет строки, sed их изменяет, awk работает с колонками и считает. Запомните базовый набор: grep -rniE и -A/-B/-C, sed 's/.../.../g' с -i.bak и -n 'Np', awk -F с $1, $NF, условиями и блоком END. Из этих кирпичей собирается почти любой разбор логов. Эти grep sed awk примеры, вместе с find, jq и curl, разобраны на практике в лекции курса по Linux об обработке текста в терминале.

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

Чем отличается grep от egrep?

egrep — устаревший псевдоним для grep -E (расширенные регулярные выражения). Современные версии GNU grep выводят предупреждение при вызове egrep, поэтому пишите grep -E.

Как найти текст во всех файлах каталога в Linux?

Используйте grep -rn "текст" /путь: -r ищет рекурсивно, -n показывает номер строки. Чтобы ограничить типы файлов, добавьте --include="*.php".

Как заменить текст во многих файлах сразу?

Объедините поиск и sed: grep -rl "old" . | xargs sed -i 's/old/new/g'. Перед этим полезно сделать коммит или резервную копию.

Как вывести в awk несколько колонок через табуляцию?

Задайте выходной разделитель: awk -v OFS='\t' '{print $1, $3}' file. Без OFS поля через запятую разделяются пробелом.

Как в sed удалить пробелы в конце строк?

Команда sed -i 's/[[:space:]]*$//' file удаляет хвостовые пробелы и табуляции во всех строках файла.

Разберите тему на видео

Эта тема подробно разобрана с практикой в курсе «Linux: с нуля до уверенного администрирования».

Перейти к курсу