На жадных против не жадных
Повторение в регулярном выражении по умолчанию является жадным : они пытаются сопоставить столько повторений, сколько возможно, и, когда это не работает, и им приходится возвращаться назад, они пытаются соответствовать одному меньшему количеству повторений за раз, пока совпадение всего шаблона не будет нашел. В результате, когда совпадение наконец произойдет, жадное повторение будет соответствовать как можно большему количеству повторений.
?
Как повторение Квантор изменяет это поведение в нежадным , называемый также неохотно ( в , например , Java ) (а иногда и «ленивый»). Напротив, это повторение сначала будет пытаться сопоставить как можно меньше повторений, и когда это не сработает, и они должны вернуться назад, они начинают сопоставлять еще одно повторение за раз. В результате, когда совпадение, наконец, происходит, неохотное повторение будет соответствовать как можно меньшему количеству повторений.
Ссылки
Пример 1: от А до Я
Давайте сравним эти две модели: A.*Z
и A.*?Z
.
Учитывая следующий вход:
eeeAiiZuuuuAoooZeeee
Шаблоны дают следующие совпадения:
Давайте сначала сосредоточимся на том, что A.*Z
делает. Когда это соответствует первому A
, то .*
, будучи жадным, сначала пытается сопоставить .
как можно больше.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Поскольку Z
не совпадает, двигатель возвращается назад и .*
должен соответствовать одному меньшему .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
Это происходит еще несколько раз, пока, наконец, мы не придем к этому:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
Теперь Z
может совпадать, поэтому общий шаблон соответствует:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
Напротив, повторение неохотно A.*?Z
вначале соответствует .
как можно меньшему количеству, а затем принимает больше .
при необходимости. Это объясняет, почему он находит два совпадения на входе.
Вот наглядное представление о том, что два шаблона совпали:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
Пример: альтернатива
Во многих приложениях два совпадения в приведенном выше вводе - это то, что является желательным, поэтому .*?
вместо жадности используется неохотное средство, .*
чтобы предотвратить чрезмерное совпадение. Однако для этого конкретного шаблона есть лучшая альтернатива, использующая класс отрицанных символов.
Шаблон A[^Z]*Z
также находит те же два совпадения, что и A.*?Z
шаблон для вышеуказанного ввода ( как видно на ideone.com ). [^Z]
это то, что называется отрицательным символьным классом : он соответствует чему угодно, кроме Z
.
Основное различие между этими двумя шаблонами заключается в производительности: будучи более строгим, класс отрицанных символов может соответствовать только одному способу для данного ввода. Не имеет значения, используете ли вы жадный или неохотный модификатор для этого шаблона. На самом деле, в некоторых разновидностях вы можете сделать еще лучше и использовать так называемый притяжательный квантификатор, который вообще не возвращается.
Ссылки
Пример 2: от A до ZZ
Этот пример должен быть иллюстративным: он показывает, как жадные, неохотные и отрицательные шаблоны классов символов по-разному совпадают при одном и том же вводе.
eeAiiZooAuuZZeeeZZfff
Это совпадения для вышеуказанного ввода:
Вот визуальное представление того, что они совпали:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
похожие темы
Это ссылки на вопросы и ответы по stackoverflow, которые охватывают некоторые темы, которые могут представлять интерес.
Одно жадное повторение может перерасти другое