Материал подготовлен для будущих студентов курса «Администратор Linux. Уровень Про».
Трудно представить современный компьютер или смартфон без тысяч файлов, хранящих в себе различную информацию. Иногда возникает необходимость что-то найти в этом многообразии, причем критерии для поиска могут быть совсем не тривиальными.
В качестве одного из возможных инструментов для поиска может применяться утилита grep. Grep (сокращение от global/regular expression/print) является одним из самых мощных и часто используемых инструментов в арсенале системного администратора и разработчика. На первый взгляд, её задача проста — найти строки в тексте, соответствующие шаблону. Например, вхождение какого-либо слова в текстовом файле Однако истинная мощь grep раскрывается при использовании регулярных выражений (regex).
В этой статье мы разберём три основных типа регулярных выражений, используемых в экосистеме grep: Basic (BRE), Extended (ERE) и Perl-compatible (PCRE) и рассмотрим несколько практических примеров.
Откуда взялись различия?
Чтобы понять разницу, нужно заглянуть в историю. Утилита grep появилась еще в первых версиях Unix. Его синтаксис регулярных выражений стал "базовым" (BRE). Позже были разработаны "расширенные" регулярные выражения (ERE), которые добавляли удобные метасимволы и делали синтаксис более интуитивным. Однако для обратной совместимости стандартный grep по умолчанию остался привязан к BRE. С появлением языка Perl его движок регулярных выражений (PCRE) стал индустриальным стандартом благодаря своей невероятной гибкости и производительности, и современные версии grep (при наличии поддержки) могут использовать и его. Далее мы рассмотрим подробнее каждый из синтаксисов.
Базовые регулярные выражения
Это режим, который используется в grep по умолчанию, если мы не указываем никакие ключи. Главная особенность BRE в том, что некоторые метасимволы (например, ?, +, {, |, ( и )) теряют своё специальное значение и воспринимаются как обычные символы. Чтобы "включить" их специальную функцию, их необходимо экранировать обратным слешем (\).
Рассмотрим пример поиска слова "go" или "goto" с использованием BRE. Обратите внимание на то, что в синтаксисе BRE оператор | (или) — это обычный символ. Чтобы использовать его как логическое "ИЛИ", нужно экранировать.
$ grep 'go\|goto' file.txt
Если мы хотим избежать использования ИЛИ можно использовать такой, менее точный вариант выражения
$ grep 'go\(to\)\?' file.txt # Ищет 'go' или 'goto' (символ 'to' может быть 0 или 1 раз)
И еще один пример. Найдём строки, где буква 'a' встречается ровно 3 раза подряд. В BRE для этого нужно экранировать фигурные скобки.
$ grep 'a\{3\}' file.txt
Расширенные регулярные выражения
Режим ERE включается ключом -E (или командой egrep, которая ныне считается устаревшей). ERE создан для удобства человека: все стандартные метасимволы (?, +, {, }, |, (, )) работают без экранирования. Это делает синтаксис более чистым и читаемым.
Вернемся к нашему примеру с goto. Вот тот же поиск "go" или "goto" в стиле ERE.
Сравните с примером BRE. Насколько проще и понятнее стал шаблон.
$ grep -E 'go|goto' file.txt
Теперь найдём строки, содержащие последовательности цифр, разделённые точками. {1,3} означает "от 1 до 3 повторений".
$ grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' access.log
Обратите внимание: Мы используем {1,3} без экранирования, а скобки () для группировки частей шаблона.
Perl-совместимые регулярные выражения
Режим PCRE можно по праву назвать вершиной эволюции регулярных выражений в grep. Включить его можно с помощью ключа -P. Он доступен не во всех версиях grep (современные дистрибутивы Linux, как правило, включают поддержку). PCRE предлагает новые возможности, недоступные в BRE и ERE: позитивный и негативный просмотр вперёд/назад (lookahead/lookbehind), "ленивые" квантификаторы, условные выражения, управляющие последовательности (\d, \w, \s) и многое другое.
Рассмотрим еще несколько примеров. Попробуем поискать трехбуквенные слова, которые НЕ являются "the". Для этого воспользуемся негативным просмотром вперёд (negative lookahead): (?!...).
$ grep -P '\b(?!the)[a-z]{3}\b' text.txt
Здесь \b обозначает границу слова, а (?!the) проверяет, что слово не равно "the", прежде чем [a-z]{3} начнёт его захватывать.
Еще один интересный пример это поиск повторяющихся слов (например, "the the"). Здесь мы используем обратные ссылки и границы слов.
$ grep -P '(\b\w+\b)\s+\1' text.txt
(\b\w+\b) — захватываем целое слово в первую группу.
\s+ — один или более пробельных символов.
\1 — обратная ссылка на содержимое первой группы (то же самое слово).
"Ленивый", но не "жадный"
По умолчанию квантификаторы в регулярных выражениях (например, .*) являются "жадными", то есть они захватывают максимально длинную строку. PCRE позволяет сделать их "ленивыми" с помощью ?.
Допустим, есть строка: <div>text1</div><div>text2</div>. "Жадный" поиск (ERE) захватит всё от первого <div> до последнего </div>
$ grep -E '<div>.*</div>' file.html
А вот "ленивый" поиск (PCRE): захватит только <div>text1</div>
$ grep -P '<div>.*?</div>' file.html
Интересные примеры
В завершении давайте применим все знания на реальных задачах, которые могут встретиться в работе. Например, для поиска всех вхождений MAC-адресов в логах мы можем воспользоваться следующим выражением в стиле ERE.
$ grep -E '([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}' system.log
здесь мы ищем вхождения в соответствии с форматом MAC-адреса: 6 групп по 2 шестнадцатеричных символа, разделённых двоеточием.
А для следующей задачи идеально подойдет PCRE. Нам необходимо найти строки, содержащие чётное количество букв 'a'. Мы будем искать строки, где буквы 'a' встречаются группами по 2, 4, 6... раз.
$ grep -P '^(?:[^a]*a[^a]*a[^a]*)*$' file.txt
Более сложный вариант:
$ grep -P '^(?=(?:[^a]*a[^a]*a)*[^a]*$)' file.txt
И еще одна задача для PCRE: извлечение всех URL из текстового файла.
$ grep -P -o 'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+(?::\d+)?(?:/[-\w$.+!*'"(),;:@&=?/~#%]*)?' text_with_links.txt
(Ключ -o выводит только совпадающую часть строки).
Заключение
Итак, давайте подведем итог рассмотренному в сегодняшней статье материалу. Выбор типа регулярных выражений в grep зависит от конкретной задачи. Если нужен быстрый поиск простого слова или шаблона с ^ и $, достаточно BRE по умолчанию.
Если вам нужны операторы |, +, ? и вы не хотите загромождать команду обратными слешами, используйте ERE (grep -E). Это "золотая середина" для 80% повседневных задач.\
Если вам нужно заглянуть вперёд/назад, использовать ленивые квантификаторы или сокращённые классы символов, подключайте тяжёлую артиллерию — PCRE (grep -P).
Владение всеми тремя режимами позволяет не просто искать текст, а буквально разговаривать с данными на их языке, быстро находя то, что скрыто от невооружённого глаза.

Хотите, чтобы grep и регулярные выражения были не разовой шпаргалкой, а частью ежедневной практики администрирования? На курсе «Администратор Linux. Уровень Про» вы системно прокачаете работу с процессами, дисками, сетью и безопасностью Linux, разберёте типовые сервисы, мониторинг и диагностику в продакшене. Готовы к серьезному обучению? Пройдите вступительный тест.
А чтобы узнать больше о формате обучения и задать вопросы экспертам, приходите на бесплатные уроки:
4 марта в 20:00. «GREP и другие регулярные выражения Linux». Записаться
16 марта в 20:00. «Списывай, но только точь-в-точь: копирование базы данных на примере MySQL». Записаться
24 марта в 20:00. «/proc, /sys, /dev: как Linux превращает железо и процессы в файлы». Записаться
Для тех, кто хочет быстро подтянуть основы, рекомендую мини-видеокурс «Linux для начинающих», сейчас всего за 10 рублей.
