Допустим, у нас есть следующие входные данные:
<amy>
(bob)
<carol)
(dean>
У нас также есть следующее регулярное выражение:
<(\w+)>|\((\w+)\)
Теперь мы получаем два совпадения (, как видно на Rubular.com ):
<amy>
соответствует, \1
захватывает amy
, \2
терпит неудачу (bob)
соответствует, \2
захватывает bob
, \1
терпит неудачу
Это регулярное выражение выполняет большую часть того, что мы хотим, а именно:
- Соответствует открывающим и закрывающим скобкам (т.е. нетмикширование)
- Он захватывает интересующую нас часть
Однако у него есть несколько недостатков:
- Схема захвата (т.е.«основная» часть) повторяется
- Это всего лишь
\w+
в этом случае, но, вообще говоря, это может быть довольно сложным, - Если это связано с обратными ссылками, то они должны быть перенумерованы для каждой альтернативы!
- Повторение делает обслуживание кошмаром!(что, если это изменится?)
- Группы по сути дублируются
- В зависимости от того, какие альтернативные совпадения, мы должны запросить разные группы
- В данном случае это всего лишь
\1
или \2
, но обычно "основная" часть может иметь собственные группы захвата!
- Это не только неудобно, но имогут быть ситуации, когда это невозможно (например, когда мы используем пользовательскую структуру регулярных выражений, ограниченную запросом только одной группы)
- Ситуация быстро ухудшается, если мы также хотимmatch
{...}
, [...]
и т. д.
Таким образом, вопрос очевиден: как мы можем это сделать, не повторяя «основной» шаблон?
Примечание: по большей части меня интересует аромат java.util.regex
, но приветствуются другие вкусы.
Приложение
В этом нет ничего новогораздел;это только иллюстрирует проблему, упомянутую выше, на примере.
Давайте рассмотрим приведенный выше пример на следующем шаге: теперь мы хотим сопоставить их:
<amy=amy>
(bob=bob)
[carol=carol]
Но не эти:
<amy=amy) # non-matching bracket
<amy=bob> # left hand side not equal to right hand side
Используя альтернативную технику, у нас работает следующее ( как видно на rubular.com ):
<((\w+)=\2)>|\(((\w+)=\4)\)|\[((\w+)=\6)\]
Как объяснено выше:
- Основной шаблон не может просто повторяться;обратные ссылки должны быть перенумерованы
- Повтор также означает кошмар обслуживания, если он когда-либо изменится
- В зависимости от того, какие альтернативные совпадения, мы должны запросить либо
\1 \2
, \3 \4
, либо \5 \6