Регулярные выражения — проверки вокруг совпадения
Предыдущий: группы и замена.
Следующий: флаги и жадность.
Идея простыми словами
Иногда нужно найти текст только при условии, что рядом что-то есть (или наоборот — чего-то нет). При этом соседний кусок не всегда нужно включать в результат.
Примеры:
- цена после знака
$, сам$в ответ не нужен; - пароль: минимум 8 символов, и есть цифра, и есть заглавная буква;
- слово
cat, за которым не идётs(чтобы отсечьcats).
Для этого служат проверки (lookaround): движок смотрит вперёд или назад, не сдвигая основной указатель и не добавляя проверку в захват (в отличие от обычных ()).
Четыре вида
| Запись | Название | Смысл |
|---|---|---|
(?=...) | опережающая, положительная | дальше должно быть ... |
(?!...) | опережающая, отрицательная | дальше не должно быть ... |
(?<=...) | ретроспективная, положительная | перед этим местом было ... |
(?<!...) | ретроспективная, отрицательная | перед этим местом не было ... |
Скобки (?:...) из прошлой статьи — обычная группа без захвата. Lookaround — отдельный механизм «подглядывания».
Опережающая проверка (?=...)
Текст:
Цена $42.50 и скидка $9
Нужны числа после доллара, без самого $ в совпадении:
(?<=\$)\d+(?:\.\d{2})?
В движках без фиксированной ширины lookbehind иногда пишут так:
(?<=\$)[0-9]+(?:\.[0-9]{2})?
Разбор (?<=\$):
| Часть | Значение |
|---|---|
(?<=\$) | прямо слева должен быть $ |
\d+ | одна или больше цифр |
(?:\.\d{2})? | необязательные копейки .50 |
Совпадения: 42.50 и 9.
Опережающий вариант (если lookbehind недоступен): \$(\d+(?:\.\d{2})?) — тогда $ попадёт в полное совпадение, а цифры — в группу 1.
«Должно быть дальше» — пароль
Требования:
- длина от 8;
- хотя бы одна заглавная латинская;
- хотя бы одна цифра;
- хотя бы один спецсимвол
@$!%*?&; - только разрешённые символы.
^(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
Читаем по блокам:
| Блок | Что проверяет |
|---|---|
^ | начало строки |
(?=.*[A-Z]) | где-то дальше есть заглавная |
(?=.*\d) | где-то дальше есть цифра |
(?=.*[@$!%*?&]) | где-то дальше есть спецсимвол |
[A-Za-z\d@$!%*?&]\{8,\} | основная часть: 8+ разрешённых символов |
$ | конец строки |
Каждый (?=...) не потребляет символы — только проверяет. Поэтому три условия можно поставить подряд.
| Пароль | Результат |
|---|---|
Abcdef1! | подходит |
abcdef1! | нет заглавной |
Abcdefgh | нет цифры и спецсимвола |
Отрицательная опережающая (?!...)
Шаблон (?!...): «на этом месте не начинается то, что дальше в скобках».
Пример: слово The, после которого не идёт пробел и fat:
(T|t)he(?!\sfat)
В строке The fat cat совпадение на первом The отсечётся (после него как раз fat). Другие вхождения the без fat останутся.
Ретроспективная (?<=...)
Текст:
The fat cat sat on the mat.
Найти fat или mat, если перед ними было The или the :
(?<=(T|t)he\s)(fat|mat)
| Часть | Значение |
|---|---|
| `(?<=(T | t)he\s)` |
| `(fat | mat)` |
Отрицательная ретроспективная (?<!...)
Найти cat, перед которым нет The / the :
(?<!(T|t)he\s)(cat)
В The cat sat on cat второе cat подойдёт, первое — нет.
Когда что выбирать
| Ситуация | Приём |
|---|---|
| Несколько независимых условий к одной строке | несколько (?=...) в начале |
| «Только если после идёт X» | (?=X) или захват с группой |
| «Только если перед был X» | (?<=X) |
| Не засорять список групп | (?:...) + lookaround |
Ограничения
- В старых движках
(?<=...)требует фиксированной ширины (например(?<=ab)— да,(?<=a+)— нет). В JavaScript lookbehind появился относительно недавно. - Сложные цепочки
(?=...)(?=...)усложняют чтение — для продакшена иногда проще проверить пароль тремя отдельными условиями в коде.
Дальше: Флаги и жадность →
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Последовательности действий для решения задач. Введение в алгоритмы. Примеры из реальной жизни для понимания, как на самом деле выглядят алгоритмы в программировании. Регулярные выражения — шаблон для поиска и проверки текста. Введение, лаборатория и маршрут обучения для новичков. Как читать шаблон слева направо — литералы, точка, классы символов, квантификаторы, якоря. Разбор логина по частям. Круглые скобки, захват частей строки, обратные ссылки, альтернатива, поиск и замена в редакторе и коде. Флаги i, m, g и аналоги в .NET; жадные и ленивые квантификаторы; почему .* захватывает слишком много. Готовые шаблоны для логов, email, URL, IP; grep, ripgrep, sed; типичные ошибки и различия движков. Универсальный алгоритм обработки - инициализация, загрузка, реакция, логика. Если вы начнёте какой-нибудь курс изучать, вероятнее всего как раз затронете в одной из первых тем алгоритмы сортировки и поиска. Оценка времени и памяти. Алгоритмическая сложность и анализ эффективности программ. Таким образом, нотация Большое O — это не только инструмент для теоретиков, но и практический ориентир для принятия архитектурных решений в самых разных областях разработки. P, NP, экспоненциальное время. Скорость работы программ.Алгоритмы
Тренировка алгоритмического мышления
Регулярные выражения
Регулярные выражения — синтаксис с нуля
Регулярные выражения — группы и замена
Регулярные выражения — флаги и жадность
Регулярные выражения — рецепты и командная строка
Алгоритм обработки
Алгоритмы сортировки и поиска
Анализ эффективности алгоритмов
Нотация Большое O
Классы временной сложности алгоритмов