В чем разница между.*? и.* регулярные выражения?

Я пытаюсь разделить строку на две части с помощью 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 делает. Когда он соответствовал первому 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.

основное различие между двумя шаблонами заключается в производительности: будучи более строгим, отрицаемый класс символов может соответствовать только одному способу для данного ввода. Не имеет значения, используете ли вы жадный или неохотный модификатор для этого шаблона. На самом деле, в некоторых вкусах вы можете сделать еще лучше и использовать то, что называется притяжательным квантором, который не отступает все.

ссылки


Пример 2: от A до ZZ

этот пример должен быть иллюстративным: он показывает, как жадные, неохотные и отрицаемые шаблоны классов символов совпадают по-разному, учитывая одно и то же вход.

eeAiiZooAuuZZeeeZZfff

это совпадения для приведенного выше ввода:

вот визуальное представление того, что они совпадение:

         ___n
        /   \              n = negated character class
eeAiiZooAuuZZeeeZZfff      r = reluctant
  \_________/r   /         g = greedy
   \____________/g

связанные разделы

это ссылки на вопросы и ответы на stackoverflow, которые охватывают некоторые темы, которые могут представлять интерес.

одно жадное повторение может outgreed другое


допустим, у вас есть:

<a></a>

<(.*)> матч a></a где <(.*?)> будет соответствовать a. Последний останавливается после первого матча >. Он проверяет один или 0 матчей .* затем следует следующее выражение.

первое выражение <(.*)> не останавливается при сопоставлении первого >. Он будет продолжаться до последнего матча >.