Для сохранения прогресса вступите в курс. Войти или зарегистрироваться.

Конспект урока

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

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

У нас есть группа символов, из которой мы выбираем либо 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)-\1

ta-tu ta-ta tu-tu


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

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

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


/(?:ta|tu)-\1

ta-tu ta-ta tu-tu


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

  • Еще одна интересная разновидность группировки без обратной связи, которая называется атомарной.

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


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

abccaxcc


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


/a(bc|b|x)cc

abccaxcc


Когда мы добавляем символы атомарной группировки ?>, происходит следующее: сначала находится символ a, затем — bc, после чего идет поиск cc. В обычном случае в примере выше поиск откатился бы до a и продолжил бы проверку с b, поскольку стоит символ альтернативы |. После этого мы бы дошли до cc и проверка бы сработала.

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

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


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

abcccaxcc


NB! Атомарная группировка не поддерживается некоторыми популярными языками программирования, в том числе JavaScript и Python.

Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →