В группе захвата
Группа захвата пытается захватить то, что ей соответствует .Это имеет некоторые важные последствия:
- Группа, которая ничего не соответствует, никогда не может ничего захватывать.
- Группа, которая соответствует только пустой строке, может захватывать только пустую строку.
- Группе, которая повторно захватывает при попытке совпадения, остается только сохранить последний захват
- В целом верно для большинства разновидностей, но регулярное выражение .NET является исключением (см. Связанный вопрос)
Вот простой шаблон, который содержит 2 группы захвата:
(\d+) (cats|dogs)
\___/ \_________/
1 2
Учитывая i have 16 cats, 20 dogs, and 13 turtles
, есть 2 совпадения (, как видно на rubular.com ):
16 cats
соответствует: группа 1 захватывает 16
, группа 2 захватывает cats
20 dogs
соответствует: группа 1 захватывает 20
группа 2 захватывает dogs
Теперь рассмотрим эту небольшую модификацию шаблона:
(\d)+ (cats|dogs)
\__/ \_________/
1 2
Теперь группа 1 соответствует \d
, то есть одной цифре.В большинстве случаев группа, которая совпадает неоднократно (в данном случае благодаря +
), получает только последнее совпадение.Таким образом, в большинстве разновидностей группа 1 захватывает только последнюю найденную цифру (, как видно на rubular.com ):
16 cats
- это совпадение: группа1 захват 6
, группа 2 захватов cats
20 dogs
является совпадением: группа 1 захватывает 0
, группа 2 захватывает dogs
Ссылки
Жадный против неохотного против отрицательного класса символов
Теперь давайте рассмотрим проблему соответствия «все между A
и ZZ
».Как оказалось, эта спецификация неоднозначна: мы придумаем 3 паттерна, которые это делают, и они приведут к различным совпадениям.Какой из них «правильный», зависит от ожидания, которое неправильно передано в исходном утверждении.
Мы используем следующее в качестве ввода:
eeAiiZooAuuZZeeeZZfff
Мы используем 3 различных шаблона:
A(.*)ZZ
дает 1 совпадение: AiiZooAuuZZeeeZZ
( как видно на ideone.com ) - Это вариант жадный ;группа 1 соответствует и захвачена
iiZooAuuZZeee
A(.*?)ZZ
дает 1 совпадение: AiiZooAuuZZ
( как видно на ideone.com ) - Это вариант неохотно ;группа 1 соответствует и захвачена
iiZooAuu
A([^Z]*)ZZ
дает 1 совпадение: AuuZZ
( как видно на ideone.com ) - Это вариант класса с отрицанием ;группа 1 сопоставлена и захвачена
uu
Вот наглядное представление того, что они сопоставили:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
См. связанный вопрос для более углубленного изучения.обработка различий между этими тремя методами.
Смежные вопросы
Возвращаясь к вопросу
Итак, давайте вернемся к вопросу и посмотримчто не так с шаблоном:
<h1>()<br
\/
1
Группа 1 соответствует пустой строке, поэтому весь шаблон в целом может соответствовать только <hr1><br
, а группа 1 может соответствовать только пустой строке.
Oneможет попытаться «исправить» это разными способами.3 очевидных варианта:
<h1>(.*)<br
;жадный <h1>(.*?)<br
;неохотно <h1>([^<]*)<br
;класс отрицанных персонажей
Вы обнаружите, что ни один из вышеперечисленных "не работает" все время; будут проблемы с некоторым HTML. Этого и следовало ожидать: регулярное выражение является «неправильным» инструментом для работы. Вы можете попытаться сделать шаблон все более и более сложным, чтобы сделать его «правильным» чаще и «неправильным» реже. Скорее всего, вы получите ужасный беспорядок, который никто не может понять и / или поддерживать, и он все равно, вероятно, не будет работать "правильно" 100% времени.