ServerAID
Найти гайд, команду, тег… ⌘ K
Shell и скрипты

grep в Linux: поиск по тексту с регулярками и примерами для Ubuntu

grep — главный инструмент поиска по содержимому файлов в Linux. Умеет работать с регулярными выражениями POSIX и PCRE, рекурсивно обходить директории, считать совпадения, показывать контекст вокруг строки. Разбираем синтаксис, ключевые флаги, тонкости с регулярками и десяток рецептов для повседневной работы администратора Ubuntu.

Зачем нужен grep

grep (Global Regular Expression Print) — стандартная утилита поиска текстовых строк по шаблону. Установлена в Ubuntu из коробки. В отличие от find, который ищет файлы, grep ищет строки внутри файлов или потока — это разные задачи, и они часто используются в связке.

Что делает grep:

  • Ищет вхождения подстроки или регулярки в файле, потоке (stdin) или рекурсивно в дереве каталогов.
  • Печатает строки, в которых нашёл (или, наоборот, не нашёл — -v).
  • Может показывать только имена файлов с совпадениями, количество совпадений, номера строк, контекст вокруг.
  • Поддерживает три диалекта регулярок: BRE (по умолчанию), ERE (-E), PCRE (-P).

Базовый синтаксис

grep [опции] <шаблон> [файл...]

Простейший вызов:

grep "TODO" main.py

Шаблон — в кавычках, чтобы спецсимволы не интерпретировал shell. Если файл не указан — grep читает stdin (полезно для конвейеров).

Топ-10 флагов на каждый день

Флаг Что делает
-r, -R рекурсивно обойти директорию
-i без учёта регистра
-v инвертировать — показать строки без совпадения
-n вывести номер строки
-c вывести только количество совпадений
-l вывести только имена файлов с совпадениями
-L наоборот — файлы без совпадений
-w только целые слова (с границей слова \b)
-x только целые строки (вся строка должна совпасть)
-q quiet, ничего не выводить, только exit code
-A N показать N строк после совпадения
-B N N строк до
-C N N строк до и после
-o вывести только совпавшую часть, не всю строку
--include="*.py" искать только в файлах по маске
--exclude-dir=.git пропустить директорию

Эти 16 флагов покрывают 95% реальных задач.

Регулярные выражения: BRE, ERE, PCRE

grep поддерживает три диалекта.

BRE — Basic Regular Expressions (по умолчанию)

Базовые метасимволы работают только если экранированы:

grep "error\\|warning" app.log    # OR в BRE — экранируется
grep "ab\\{2,4\\}" file           # повторение — тоже
grep "\\(group\\)" file           # группировка — тоже

Это неудобно, поэтому большинство админов используют ERE.

ERE — Extended Regular Expressions (флаг -E)

Метасимволы работают без экранирования:

grep -E "error|warning" app.log
grep -E "ab{2,4}" file
grep -E "(group1|group2)" file

egrep — алиас для grep -E, до сих пор работает, но считается deprecated.

PCRE — Perl Compatible Regular Expressions (флаг -P)

Самый мощный диалект с поддержкой lookahead/lookbehind, нежадных квантификаторов, \d, \s, \w:

# Цифры подряд (3 и больше)
grep -P "\d{3,}" file

# IP-адреса (упрощённо)
grep -P "\b(?:\d{1,3}\.){3}\d{1,3}\b" /var/log/auth.log

# Lookahead: error, после которого НЕТ "ignored"
grep -P "error(?!.*ignored)" app.log

PCRE на Ubuntu доступен в стандартной поставке grep — отдельной установки не нужно.

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

Когда нужно понять, где в файле произошло событие:

# 3 строки до и после каждого совпадения "ERROR"
grep -C 3 "ERROR" /var/log/app.log

# Только после (для трейсбеков)
grep -A 10 "Traceback" app.log

# Только до (для предыстории ошибки)
grep -B 5 "OOM killer" /var/log/syslog

Рекурсивный поиск

# Все файлы с TODO в проекте
grep -rn "TODO" .

# Только в .py файлах, пропуская .git и venv
grep -rn --include="*.py" --exclude-dir={.git,venv,node_modules} "TODO" .

# Только имена файлов с упоминанием функции
grep -rl "calculate_total" src/

-r идёт по symlinks с осторожностью (раньше было -R, теперь оба ведут себя одинаково в современном grep). Если symlink ведёт в бесконечный цикл — grep автоматически прерывает обход.

grep в конвейерах

Самый частый сценарий — фильтрация вывода других команд:

# Запущенные процессы python
ps aux | grep python

# Только установленные пакеты, относящиеся к nginx
dpkg -l | grep nginx

# Логи systemd-сервиса за последний час
journalctl -u nginx --since "1 hour ago" | grep -i error

# IP-адреса в логах
grep -oE "([0-9]{1,3}\\.){3}[0-9]{1,3}" /var/log/auth.log | sort -u

Классическая ловушка ps aux | grep python — сам grep попадает в результаты. Решение — двойной grep с инвертом:

ps aux | grep python | grep -v grep

Или хитрее — через регулярку, которая не совпадает сама с собой:

ps aux | grep "[p]ython"

[p] — это символьный класс из одной буквы p, совпадает с p. Сам шаблон [p]ython в ps не показан, потому что grep видит свою команду как grep [p]ython, а не python.

Производительность на больших файлах

grep — однопоточный, но очень быстрый: 100-мегабайтный файл сканируется за секунды. Для очень больших файлов (десятки гигабайт) есть оптимизации:

# Указать LANG=C — отключает поддержку Unicode, быстрее на ASCII
LANG=C grep "ERROR" huge.log

# Параллельный grep через GNU parallel
cat huge.log | parallel --pipe --block 10M grep "ERROR"

# ripgrep — альтернатива grep, на порядки быстрее
sudo apt install ripgrep
rg "ERROR" huge.log

ripgrep (rg) — современный заменитель grep: автоматически пропускает .gitignore-исключения, использует PCRE по умолчанию, многопоточный. Для интерактивной работы — лучше grep, для CI-скриптов — оба работают.

Десять рецептов

# 1. Сколько раз слово встретилось в файле
grep -c "TODO" main.py

# 2. Только уникальные совпадения (через sort)
grep -oE "[a-zA-Z_]+@[a-zA-Z.]+" emails.txt | sort -u

# 3. Логи без noise — все ERROR кроме известных
grep "ERROR" app.log | grep -vE "(retry|expected)"

# 4. Найти конфиг с конкретной директивой
sudo grep -rl "server_name" /etc/nginx/

# 5. Поиск кириллицы
grep -P "[А-Яа-я]" mixed.txt

# 6. Количество строк, НЕ начинающихся с #
grep -cv "^#" /etc/nginx/nginx.conf

# 7. Пустые строки — найти и убрать
grep -v "^$" file.txt > file.cleaned.txt

# 8. Большие числа (от 1000)
grep -E "[0-9]{4,}" data.txt

# 9. Сравнение через -f с файлом паттернов
grep -f keywords.txt big-file.txt

# 10. Конкретная функция в кодовой базе
grep -rwn --include="*.go" "func handleLogin" .

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

Шаблон не в кавычках

grep *.conf file — shell сначала раскроет *.conf в список файлов, и grep увидит уже неожиданные аргументы. Всегда в кавычках: grep "*.conf" file.

Спецсимволы в шаблоне

Точка . в регулярке — это любой символ. Чтобы искать буквальную точку, экранируйте:

# Найдёт "config.yaml", "configXyaml" и так далее
grep "config.yaml" file

# Только буквальную точку
grep "config\\.yaml" file
# или с -F (fixed string — без регулярок)
grep -F "config.yaml" file

-F (или алиас fgrep) — поиск буквальной строки без интерпретации как регулярки. Быстрее, безопаснее, читабельнее для простых случаев.

-E vs PCRE

-E — extended POSIX, -P — Perl. Многие думают, что -E поддерживает \d, \s — нет, это PCRE. Под -E нужно [0-9], [[:space:]].

grep vs ack vs ripgrep

Утилита Скорость Регулярки по умолчанию Игнорирует .git и .gitignore Установка
grep базовая BRE нет предустановлен
egrep (grep -E) базовая ERE нет предустановлен
ack медленнее grep PCRE да sudo apt install ack
ripgrep (rg) в 5–10 раз быстрее grep PCRE да sudo apt install ripgrep

Для скриптов и системных задач — grep (везде есть, стабильный). Для интерактивного поиска по коду — ripgrep (быстрее, умнее с гитом).

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

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

find ищет файлы по их свойствам (имя, размер, время, права). grep ищет строки внутри файлов. Часто работают в связке: find . -name "*.log" -exec grep "ERROR" {} + — найти ERROR во всех .log-файлах.

Как искать с учётом или без учёта регистра?

По умолчанию grep чувствителен к регистру. Флаг -i отключает это: grep -i "warning" app.log найдёт WARNING, Warning, warning и любую другую комбинацию. Если шаблон должен быть точно с регистром — флаг не используйте.

Как исключить строки, содержащие шаблон?

Флаг -v инвертирует: показывает строки, в которых шаблон не найден. Например, grep -v "^#" config.txt покажет все строки, не начинающиеся с # — то есть весь конфиг без комментариев.

Почему grep не работает с регуляркой типа \d?

\\d — это синтаксис PCRE (Perl). Базовый grep использует POSIX, где нужно [0-9]. Чтобы использовать perl-совместимые регулярки, нужен флаг -P: grep -P "\\d+" file.

Как искать строку, начинающуюся с конкретного слова?

Якорь ^ — начало строки: grep "^ERROR" app.log найдёт строки, начинающиеся точно с ERROR. Аналогично $ для конца строки: grep "completed$" log. Для целого слова (с границами) — флаг -w: grep -w "API" file совпадёт с "API ", " API,", но не с "APIs".

Что запомнить

  • grep ищет строки в файлах или потоке. По умолчанию POSIX BRE.
  • Шаблон всегда в кавычках, чтобы shell не интерпретировал спецсимволы.
  • Топ-флаги: -i, -v, -n, -r, -l, -c, -A/-B/-C для контекста.
  • Регулярки: BRE (по умолчанию), -E для ERE, -P для PCRE.
  • Рекурсивный поиск: grep -rn --include "*.py" --exclude-dir .git.
  • Для конвейеров с пробелами/спецсимволами — -F (буквальная строка).
  • На больших файлах — LANG=C grep или ripgrep для многопоточности.
  • grep "[p]roc" — трюк, чтобы grep не нашёл сам себя в выводе ps.

Похожие материалы

Shell и скрипты

awk в Linux: обработка табличных данных и логов с примерами

awk — миниатюрный язык программирования для построчной обработки текста. Идеально подходит для работы с таблицами, CSV, логами и любыми данными со столбцами: автоматически разделяет каждую строку на поля и даёт удобный синтаксис фильтрации и преобразования. Разбираем базовый синтаксис, переменные, шаблоны, действия и десяток рецептов для повседневной работы администратора Ubuntu.

Редакция
Shell и скрипты

find в Linux: руководство по поиску файлов с примерами для Ubuntu

find — самый мощный инструмент поиска файлов в Linux. В отличие от locate он смотрит файловую систему вживую, поддерживает фильтрацию по имени, размеру, времени изменения, правам, владельцу и умеет выполнять действие над найденным. Разбираем синтаксис, ключевые предикаты и десяток рецептов, которые покрывают 95% реальных задач администратора Ubuntu.

Редакция
Shell и скрипты

sed на Linux: замена строк, правка in-place и регулярки

sed (stream editor) — стандартная команда Linux для построчной обработки текста: замена, удаление, печать строк по шаблону. Работает с потоком (pipe) или файлами, поддерживает in-place редактирование. Базовый инструмент шелл-скриптов после `grep` и `awk`.

Редакция
Shell и скрипты

wget на Linux: скачивание файлов, дозакачка и зеркало сайта

wget — стандартная утилита Linux для скачивания файлов по HTTP, HTTPS и FTP. Умеет дозакачивать прерванное, ходить рекурсивно по ссылкам, ограничивать скорость и работать без интерактива — поэтому это базовый инструмент скриптов установки, скачивания дистрибутивов и зеркалирования сайтов.

Редакция