FAQ: вопросы о регулярных выражениях
Ответы на частые вопросы о regex, RegexLab, синтаксических отличиях между языками и отладке сложных паттернов.
Регулярные выражения (regex, regexp) — это формальный язык для описания шаблонов поиска в тексте. С их помощью можно в одну строку кода описать сложный критерий для поиска, замены или извлечения данных из строк.
Где используются регулярные выражения:
— Валидация форм: проверка корректности email, телефона, почтового индекса прямо в браузере
— Парсинг логов: извлечение дат, IP-адресов, кодов ошибок из файлов журналов
— Рефакторинг кода: массовая замена шаблонов в IDE (Vim, VSCode, JetBrains)
— Обработка данных: очистка, нормализация и трансформация текстовых данных
— Web scraping: извлечение структурированных данных из HTML
— Командная строка: grep, sed, awk — все используют regex
RegexLab позволяет строить и тестировать паттерны в реальном времени — вы сразу видите совпадения, группы захвата и объяснение каждого токена.
Жадный квантификатор (*, +, {n,m}) пытается захватить как можно больше символов, и только если это мешает общему совпадению паттерна, отступает (backtracking).
Ленивый квантификатор (*?, +?, {n,m}?) захватывает минимум — расширяется только при необходимости.
Наглядный пример. Текст: <b>жирный</b> и <i>курсив</i>
— Паттерн <.*> (жадный): найдёт одно совпадение — всё от первого < до последнего >
— Паттерн <.*?> (ленивый): найдёт четыре совпадения — каждый тег отдельно
Ленивый вариант обычно нужен, когда вы ищете несколько отдельных шаблонов в тексте, а не один большой блок. Жадный удобен, когда нужно захватить весь блок от открывающего до закрывающего маркера.
Именованные группы позволяют обратиться к захваченному фрагменту по имени, а не по порядковому номеру. Это делает код более читаемым и устойчивым к изменениям паттерна.
Синтаксис зависит от языка:
— Python / PCRE: (?P<name>pattern), доступ: match.group('name')
— JavaScript (ES2018+): (?<name>pattern), доступ: match.groups.name
— Java: (?<name>pattern), доступ: matcher.group("name")
Пример — разобрать дату 2024-03-15:
Паттерн JS: (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Результат: groups.year = "2024", groups.month = "03", groups.day = "15"
В RegexLab именованные группы поддерживаются в синтаксисе JavaScript ((?<name>)) — совпадения отображаются в панели совпадений с именами групп.
Lookahead и lookbehind — конструкции предпросмотра нулевой ширины. Они проверяют наличие или отсутствие символов вокруг текущей позиции, но не включают их в совпадение. Это принципиально: захваченный результат будет только то, что перед/после конструкции.
Четыре вида:
— (?=...) позитивный lookahead: следующие символы ДОЛЖНЫ совпасть
— (?!...) негативный lookahead: следующие символы НЕ должны совпасть
— (?<=...) позитивный lookbehind: предыдущие символы ДОЛЖНЫ совпасть
— (?<!...) негативный lookbehind: предыдущие символы НЕ должны совпасть
Пример: найти число перед знаком рубля, но не включать знак в результат:(?<=₽)\d+ — найдёт 1500 в строке Цена: ₽1500
RegexLab работает на основе встроенного JavaScript RegExp. Это означает полную поддержку современного ECMA-262 синтаксиса:
— Все базовые метасимволы: . * + ? ^ $ | [] {} ()
— Классы символов: \d \w \s и их инверсии
— Флаги: g i m s u
— Именованные группы: (?<name>) (ES2018)
— Lookahead: (?=) (?!)
— Lookbehind: (?<=) (?<!) (ES2018)
— Незахватывающие группы: (?:)
Синтаксис (?P<name>) из Python не поддерживается — используйте (?<name>). Также не поддерживаются POSIX-классы ([:alpha:]) и рекурсивные паттерны (PCRE-специфика).
Методика отладки сложных паттернов:
1. Разбейте на части. Начните с простейшей части паттерна и убедитесь, что она работает. Затем добавляйте элементы по одному. RegexLab обновляет результат в реальном времени — вы мгновенно видите эффект каждого изменения.
2. Используйте панель объяснения. В RegexLab каждый токен паттерна разбирается с описанием: что означает \b, (?:), {2,4}. Это помогает найти токен, который работает не так, как ожидалось.
3. Проверяйте граничные случаи. Добавьте в тестовый текст строки, которые не должны совпасть. Убедитесь, что они действительно не совпадают.
4. Катастрофический возврат. Если паттерн зависает — подозревайте вложенные квантификаторы вроде (a+)+ или (.|\n)*. Замените на атомарные группы или притяжательные квантификаторы (если язык поддерживает).
Самые частые причины несовместимости между Python и JavaScript:
1. Синтаксис именованных групп:
Python: (?P<name>...) и (?P=name) для обратных ссылок
JavaScript: (?<name>...) и \k<name> для обратных ссылок
2. Lookbehind переменной ширины:
JavaScript ES2018 поддерживает (?<=a*). Python требует фиксированной ширины в lookbehind — (?<=abc) работает, (?<=a+) вызовет ошибку.
3. Глобальный поиск:
Python re.match() ищет только в начале строки. re.search() ищет первое совпадение. re.findall() — все совпадения (аналог флага g в JS).
4. Unicode:
В Python 3 строки Unicode по умолчанию. В JavaScript для корректной работы с Unicode нужен флаг u: тогда \w включает Unicode-буквы при наличии \p{L}.
Да, в RegexLab есть встроенный блок замены (Replace). Введите паттерн в поле regex, тестовый текст в поле ввода, а строку замены — в поле «Replacement».
В строке замены доступны следующие подстановки:
— $1, $2, ... — содержимое первой, второй и т.д. группы захвата
— $& — всё совпадение целиком
— $` — текст до совпадения
— $' — текст после совпадения
— $<name> — содержимое именованной группы
Пример: заменить формат даты с 2024-03-15 на 15.03.2024:
Паттерн: (\d{4})-(\d{2})-(\d{2})
Замена: $3.$2.$1
Результат замены обновляется в реальном времени. Кнопка «📋 Копировать результат» позволяет скопировать итоговый текст в буфер обмена.
Флаг g (global) заставляет регулярное выражение находить все совпадения в строке, а не останавливаться на первом.
Поведение методов JavaScript зависит от наличия флага:
— str.match(/re/) — возвращает первое совпадение с деталями
— str.match(/re/g) — возвращает массив всех совпадений (без деталей групп)
— str.replace(/re/, fn) — заменяет только первое вхождение
— str.replace(/re/g, fn) — заменяет все вхождения
— str.matchAll(/re/g) — итератор всех совпадений с деталями групп (требует флаг g)
В RegexLab флаг g включён по умолчанию — именно поэтому панель «Совпадения» показывает все найденные результаты. Отключить его можно нажав кнопку g в блоке флагов.
В RegexLab поле тестирования поддерживает многострочный ввод — просто нажмите Enter для перехода на новую строку. Для работы с многострочным текстом важно понимать, какой флаг нужен в вашей ситуации:
Флаг m (multiline): нужен, если вы используете ^ и $. Без него ^ совпадает только с началом всего текста, а $ — с концом. С флагом m они совпадают с началом и концом каждой строки.
Флаг s (dotAll): нужен, если паттерн должен захватывать несколько строк через точку .. Без него . не совпадает с символом новой строки. С флагом s точка означает «любой символ включая \n».
Пример — найти всё содержимое между тегами, даже если оно на нескольких строках:
Паттерн: <div>.*?</div> с флагами gs
Включите нужные флаги кнопками m и s в панели флагов RegexLab.
// Тестируйте regex в реальном времени
Откройте RegexLab и протестируйте любой из паттернов прямо сейчас. Или прочитайте полный справочник по синтаксису — там разобраны все конструкции с примерами.
Открыть RegexLab Читать справочник