В чем разница между.*? и.* регулярные выражения?
Я пытаюсь разделить строку на две части с помощью regex. Строка имеет следующий формат:
text to extract<number>
Я использую (.*?)<
и <(.*?)>
которые работают нормально, но после прочтения в regex немного, я только начал задаваться вопросом, почему мне нужно ?
в выражениях. Я сделал это только после того, как нашел их через этот сайт, поэтому я не совсем уверен, в чем разница.
3 ответов
это разница между жадных и нежадных квантификаторов.
рассмотрим ввод 101000000000100
.
используя 1.*1
, *
жадный - он будет соответствовать до конца, а затем вернуться, пока он не может соответствовать 1
С 1010000000001
..*?
не жадный. *
ничего не матч, а потом будем стараться соответствовать лишние символы до матчей 1
в итоге сопоставления 101
.
все кванторы имеют не-жадный режим:.*?
, .+?
, .{2,6}?
, и даже .??
.
в вашем случае аналогичный шаблон может быть <([^>]*)>
- сопоставление ничего, кроме знака больше, чем (строго говоря, он соответствует нулю или более символов, кроме >
между <
и >
).
посмотреть Лист Квантор Чит.
на greedy против non-greedy
повторение в регулярном выражении по умолчанию жадина: они пытаются сопоставить как можно больше повторений, и когда это не работает, и им приходится отступать, они пытаются сопоставить один меньше повторений за раз, пока не будет найдено совпадение всего шаблона. В результате, когда матч, наконец, происходит, жадное повторение будет соответствовать как много повторений насколько это возможно.
на ?
как Квантор повторения изменяет это поведение в нежадный, также называемый хочет (например, Java) (а иногда и "ленивый"). Напротив, это повторение сначала попытается соответствовать as несколько повторения, насколько это возможно, и когда это не работает, и они должны вернуться, они начинают соответствовать еще одному повторению за раз. В результате, когда матч, наконец, происходит, неохотное повторение будет соответствовать как несколько повторений, как вероятный.
ссылки
Пример 1: от A до Z
давайте сравним эти две модели:A.*Z
и A.*?Z
.
учитывая следующие данные:
eeeAiiZuuuuAoooZeeee
шаблоны дают следующие совпадения:
-
A.*Z
дает 1 матч:AiiZuuuuAoooZ
(посмотреть на rubular.com) -
A.*?Z
дает 2 матча:AiiZ
иAoooZ
(смотрите дальше rubular.com)
A.*Z
делает. Когда он соответствовал первому A
, the .*
, будучи жадным, сначала пытается соответствовать, как много .
как это возможно.
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
.
основное различие между двумя шаблонами заключается в производительности: будучи более строгим, отрицаемый класс символов может соответствовать только одному способу для данного ввода. Не имеет значения, используете ли вы жадный или неохотный модификатор для этого шаблона. На самом деле, в некоторых вкусах вы можете сделать еще лучше и использовать то, что называется притяжательным квантором, который не отступает все.
ссылки
- regular-expressions.info/Repetition -альтернатива лени, Отрицаемые Классы Символов и Притяжательные Квантификаторы
Пример 2: от A до ZZ
этот пример должен быть иллюстративным: он показывает, как жадные, неохотные и отрицаемые шаблоны классов символов совпадают по-разному, учитывая одно и то же вход.
eeAiiZooAuuZZeeeZZfff
это совпадения для приведенного выше ввода:
-
A[^Z]*ZZ
дает 1 матч:AuuZZ
(как видно на ideone.com) -
A.*?ZZ
дает 1 матч:AiiZooAuuZZ
(как видно на ideone.com) -
A.*ZZ
дает 1 матч:AiiZooAuuZZeeeZZ
(как видно на ideone.com)
вот визуальное представление того, что они совпадение:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
связанные разделы
это ссылки на вопросы и ответы на stackoverflow, которые охватывают некоторые темы, которые могут представлять интерес.
одно жадное повторение может outgreed другое
допустим, у вас есть:
<a></a>
<(.*)>
матч a></a
где <(.*?)>
будет соответствовать a
.
Последний останавливается после первого матча >
. Он проверяет один
или 0 матчей .*
затем следует следующее выражение.
первое выражение <(.*)>
не останавливается при сопоставлении первого >
. Он будет продолжаться до последнего матча >
.