- Группировка с обратной связью
- Именованные группы
- Группировка без обратной связи
- Атомарная группировка
В этом уроке мы рассмотрим дополнительные возможности и различные виды группировки.
Группировка с обратной связью
У нас есть группа символов, из которой мы выбираем либо 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
При такой группировке дальнейший поиск прекращается, после того как мы прошли все альтернативы из группы.
Подробный алгоритм можно описать так:
- Поиск начинается с первого символа анализируемой строки
- Если найдено совпадение до атомарной группы, то происходит поочередная подстановка вариантов
- При первом найденном совпадении перебор вариантов завершается и продолжается поиск символов после атомарной группы
- Если совпадение с регулярным выражением неполное, то поиск заканчивается. Это не зависит от того, были ли опробованы остальные варианты из группы
- Дальнейший поиск по строке выполняется снова для всего регулярного выражения, но уже со следующего по порядку символа анализируемой строки
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.