← Весь справочник

grep

Поиск строк по шаблону в файлах и выводе команд

grep читает файлы (или стандартный ввод) построчно и печатает строки, в которых нашёлся шаблон. Шаблон — регулярное выражение или, с -F, обычная строка. В песочнице — GNU grep 3.11.

Синтаксис

grep [опции] 'шаблон' [файл…]
grep [опции] -e 'шаблон1' -e 'шаблон2' [файл…]
команда | grep [опции] 'шаблон'

Без файлов grep читает stdin (с -r — текущий каталог). Файл - тоже означает stdin.

Код возврата: 0 — нашлась хотя бы одна строка, 1 — ничего не нашлось, 2 — ошибка (нет файла, неверная регулярка). С -q при найденном совпадении будет 0, даже если какой-то файл прочитать не удалось.

Опции

Как понимать шаблон

ОпцияЧто делает
-Gбазовые регулярки (BRE) — режим по умолчанию
-Eрасширенные регулярки (ERE): + ? | ( ) { } без обратных слэшей
-Fшаблон — обычная строка, никаких спецсимволов
-PPerl-регулярки (PCRE): \d, \s, ленивые *?, просмотр (?=…), \K
-e шаблонзадать шаблон; можно повторять — совпадение с любым. Нужен, если шаблон начинается с -
-f файлвзять шаблоны из файла, по одному на строку
-iбез учёта регистра; --no-ignore-case — отменить
-wшаблон должен совпасть с целым словом (слово — буквы, цифры, _)
-xшаблон должен совпасть со всей строкой целиком
-vвыбрать строки, где совпадения нет

Что и как печатать

ОпцияЧто делает
-cвместо строк — их число (совпавших строк, не совпадений), для каждого файла
-l / -Lтолько имена файлов, где совпадение есть / где его нет
-oтолько совпавшие фрагменты, каждый на отдельной строке
-qничего не печатать, только код возврата; останавливается на первом совпадении
-nномер строки перед строкой: 12:текст
-bсмещение в байтах от начала файла
-H / -hпечатать / не печатать имя файла перед строкой. По умолчанию имя есть, если файлов больше одного (или -r)
-m Nостановиться после N совпавших строк в каждом файле
-sне сообщать о несуществующих и нечитаемых файлах
--color=autoподсвечивать совпадения (always — даже в конвейере)
--line-bufferedсбрасывать вывод после каждой строки — нужно в tail -f … | grep …
-Zпосле имени файла ставить нулевой байт (для xargs -0)
-Tвыравнивать вывод табуляцией после префиксов
--label=имяимя, которое показывать для stdin

Контекст

ОпцияЧто делает
-A Nпоказать ещё N строк после совпадения
-B Nпоказать N строк до совпадения
-C N / -NN строк до и после (-2 — то же, что -C 2)
--group-separator=STR / --no-group-separatorчем разделять группы контекста (по умолчанию --) / не разделять

Файлы и каталоги

ОпцияЧто делает
-rискать рекурсивно в каталогах; символические ссылки внутри не открывает
-Rто же, но идёт по всем символическим ссылкам
--include='*.conf'смотреть только файлы, подходящие под маску (можно повторять)
--exclude='*.log'пропускать файлы по маске
--exclude-dir=.gitне заходить в каталоги по маске
-aсчитать двоичный файл текстом и печатать совпавшие строки
-Iмолча пропускать двоичные файлы
-zстроки разделены нулевым байтом, а не \n (для вывода find -print0)

Формат вывода

Строка вывода собирается из префиксов: имя_файла:номер:смещение:текст. Строки контекста (-A/-B/-C) отделяются не :, а - (app.log-14-текст), а между несмежными группами печатается --.

Примеры

printf 'INFO start\nERROR disk full\nWARN slow\nerror retry\nINFO stop\n' > app.log

# строки с error в любом регистре, с номерами
grep -in error app.log

# всё, кроме строк INFO
grep -v INFO app.log

# несколько шаблонов: через -E и | или через несколько -e
grep -E 'ERROR|WARN' app.log
grep -e ERROR -e WARN app.log

# шаблоны из файла
printf 'ERROR\nWARN\n' > patterns.txt
grep -f patterns.txt app.log

# сколько строк совпало и сколько всего вхождений
grep -ci error app.log
grep -oi error app.log | wc -l

# контекст: строка WARN, одна до и одна после
grep -C1 WARN app.log

# точка как точка, а не «любой символ»
printf 'v1.2.3\nv1x2y3\n' | grep -F '1.2.3'

# целое слово и целая строка
printf 'cat\ncatalog\nthe cat\n' | grep -w cat
printf 'cat\ncatalog\nthe cat\n' | grep -x cat

# рекурсивно: только *.conf, без каталога .git, только имена файлов
grep -rl --include='*.conf' --exclude-dir=.git 'listen' /etc

# в условии скрипта
if grep -q '^ERROR' app.log; then echo 'есть ошибки'; fi

# значение после ключа: \K отбрасывает всё, что совпало до него
echo 'port=8080' | grep -oP 'port=\K\d+'

# только первое совпадение
grep -m1 INFO app.log

# имена файлов с совпадениями — безопасно для xargs
grep -rlZ 'listen' /etc/nginx | xargs -0 ls -l

Подводные камни

  • -c считает строки, а не совпадения. В строке error error будет 1. Каждое вхождение считай через grep -o … | wc -l.
  • ps aux | grep nginx находит и сам grep. Возьми одну букву в скобки — grep '[n]ginx': шаблон по-прежнему совпадает с nginx, но строка запуска самого grep ([n]ginx) уже не подходит. Ещё проще — pgrep.
  • Базовые регулярки (без -E) понимают + ? | ( ) { } буквально. grep 'a+b' ищет строку a+b. Пиши grep -E 'a+b' или grep 'a\+b'. Подробнее — Регулярные выражения.
  • \d и \t работают только с -P. Без него \d — это просто буква d, а \t — буква t. Для цифр есть [0-9] или [[:digit:]], табуляцию можно передать как $'\t'.
  • Шаблон без кавычек раскроет оболочка: *, ?, […] и $ могут измениться ещё до запуска grep. Бери шаблон в одинарные кавычки.
  • -r не ходит по символическим ссылкам внутри каталога, -R — ходит. Маски --include и --exclude тоже бери в кавычки.
  • Двоичные файлы. Если в файле есть нулевые байты, grep напишет binary file matches вместо строки. -a покажет строки, -I пропустит такие файлы.
  • -o с -c всё равно считает строки, а -o вместе с -v ничего не печатает.
  • Локаль. В песочнице локаль POSIX, поэтому -i не сравнивает русские буквы без учёта регистра (Привет и привет различаются), а . совпадает с одним байтом, а не с кириллической буквой. С LC_ALL=C.utf8 оба случая работают как ожидается.

См. также

Регулярные выражения · sed · awk · find · xargs · wc