Зарегистрируйтесь, чтобы продолжить обучение

Группировка и обратная связь Регулярные выражения (Regexp)

В этом уроке мы рассмотрим дополнительные возможности и различные виды группировки.

Группировка с обратной связью

У нас есть группа символов, из которой мы выбираем либо ta, либо tu:


/(ta|tu)/

ta-tu ta-ta tu-tu


Предположим, что мы хотим найти только те подстроки, в которых левая и правая части совпадают: ta - ta и tu - tu. Попробуем дополнить наше выражение еще одним условием «или» и увидим, что реализовать задуманное не удалось:


/(ta|tu)-(ta|tu)/

ta-tu ta-ta tu-tu


Здесь поможет группировка с обратной связью. Чтобы сделать ее, мы используем специальное обозначение \1. Оно указывает, что символы из первой группы нужно подставить вместо \1.

Таким образом, совпадают подстроки с одинаковыми левыми и правыми частями:


/(ta|tu)-\1/

ta-tu ta-ta tu-tu


По умолчанию все созданные группы символов записываются в специальную область памяти и маркируются символами от \1 до \9. Если бы мы использовали квантификацию, то это не повлияло бы на результат. Дело в том, что квантификация не участвует в обратной связи — берется только первое вхождение в область памяти:


/(ta|tu)+-\1/

ta-tu ta-ta tu-tu


Именованные группы

Если вы используете несколько групп, то не очень удобно запоминать их по номерам. Гораздо проще пользоваться именами. Для этого нужно добавить ?<имя> после открытия скобки:


/(?<group1>ta|tu)-\k<group1>/

ta-tu ta-ta tu-tu


Теперь нам удобнее работать с группой в своем коде — можно ссылаться на группу по имени group1.

Символ k используется для обратной ссылки на именованную группу. В данном случае, \k<group1> означает обратную ссылку на группу с именем group1. Это означает, что после символа - должно быть то же самое значение, что и в группе group1.

Группировка без обратной связи

Мы можем отключить обратную связь, поставив ?: внутри нашей группы:


/(?:ta|tu)-\1/

ta-tu ta-ta tu-tu


После этого группа перестанет сохраняться в специальную область памяти. При ее вызове возникнет ошибка, потому что такой группы в памяти не существует. При таком подходе регулярное выражение становится очень сложно читать, однако оно работает быстрее.

Это вполне рабочий метод. Он особенно подходит, если вы хотите, чтобы лишние группы не занимали много места и не мешали заниматься дальнейшей группировкой.

Атомарная группировка

Еще одна интересная разновидность группировки без обратной связи — атомарная. Атомарная группировка не поддерживается некоторыми популярными языками программирования, в том числе JavaScript и Python. Тем не менее можно найти решения для их эмуляции на имеющихся конструкциях.

Для атомарной группировки вместо : используется символ >:


/a(?>bc|b|x)cc/

abcc axcc abcc


Когда мы добавляем символы атомарной группировки ?>, происходит следующее:

  • Сначала находится символ a
  • Затем — bc
  • Затем — идет поиск cc

Давайте разберемся, как она работает. Если мы уберем символы ?>, то регулярное выражение находит три подстроки — abcc, axcc и abcc:


/a(bc|b|x)cc/

abcc axcc abcc


Рассмотрим подробнее этот пример. В обычном случае поиск откатился бы до a и продолжил бы проверку с b, потому что стоит символ альтернативы |. После этого мы бы дошли до cc — и проверка бы сработала.

При атомарной группировке возврат по строке до символа a отключается. Происходит дальнейшее движение по альтернативам bc -> b -> x, а после x — сопоставление cc.

Когда найдено первое совпадение из атомарной группы (?>bc|b|x), другие варианты из этой группы не рассматриваются. Дальше идет поиск со следующего символа из анализируемой строки с первого символа регулярного выражения.

Мы могли бы найти совпадение с подстрокой с атомарной группировкой, только если бы добавили к abcc еще один символ c:


/a(?>bc|b|x)cc/

abccc axcc abcc


При такой группировке дальнейший поиск прекращается, после того как мы прошли все альтернативы из группы.

Подробный алгоритм можно описать так:

  1. Поиск начинается с первого символа анализируемой строки
  2. Если найдено совпадение до атомарной группы, то происходит поочередная подстановка вариантов
  3. При первом найденном совпадении перебор вариантов завершается и продолжается поиск символов после атомарной группы
  4. Если совпадение с регулярным выражением неполное, то поиск заканчивается. Это не зависит от того, были ли опробованы остальные варианты из группы
  5. Дальнейший поиск по строке выполняется снова для всего регулярного выражения, но уже со следующего по порядку символа анализируемой строки

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Верстка на HTML5 и CSS3, Программирование на JavaScript в браузере, разработка клиентских приложений используя React
10 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на Python, Разработка веб-приложений и сервисов используя Django, проектирование и реализация REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на Java, Разработка веб-приложений и микросервисов используя Spring Boot, проектирование REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на PHP, Разработка веб-приложений и сервисов используя Laravel, проектирование и реализация REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на JavaScript в браузере и на сервере (Node.js), разработка бекендов на Fastify и фронтенда на React
16 месяцев
с нуля
Старт 26 декабря
профессия
Программирование на JavaScript, разработка веб-приложений, bff и сервисов используя Fastify, проектирование REST API
10 месяцев
с нуля
Старт 26 декабря
профессия
новый
Git, JavaScript, Playwright, бэкенд-тесты, юнит-тесты, API-тесты, UI-тесты, Github Actions, HTTP/HTTPS, API, Docker, SQL
8 месяцев
c опытом
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»