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


Я пытаюсь разделить строку на две части с помощью regex. Строка имеет следующий формат:

text to extract<number>

Я использую (.*?)< и <(.*?)> которые работают нормально, но после чтения в регулярное выражение немного, я только начал задаваться вопросом, зачем мне нужен ? в выражениях. Я сделал это только после того, как нашел их на этом сайте, поэтому я не совсем уверен, в чем разница.

3 90

3 ответа:

это разница между жадными и не жадными кванторами.

рассмотреть вход 101000000000100.

используя 1.*1,* жадный - он будет соответствовать весь путь до конца, а затем вернуться, пока он не может соответствовать 1 С 1010000000001.
.*? не жадный. * не будет соответствовать ничего, но затем будет пытаться соответствовать дополнительные символы, пока он не соответствует 1 в итоге сопоставления 101.

все кванторы имеют a не жадный режим:.*?,.+?,.{2,6}?, и даже .??.

в вашем случае аналогичная картина может быть <([^>]*)> - соответствие чему-либо, кроме знака больше, чем (строго говоря, он соответствует нулю или более символов, отличных от > между < и >).

посмотреть Квантор Шпаргалка.

на жадных против не-жадных

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

The ? как Квантор повторения изменяет это поведение в нежадный, также называемый хочет (например, Java) (а иногда и "ленивый"). Напротив, это повторение сначала попытается соответствовать как несколько повторений, как это возможно, и когда это не работает, и они должны вернуться, они начинают соответствовать еще один репт время. В результате, когда матч, наконец, происходит, неохотное повторение будет соответствовать как несколько повторений, как вероятный.

ссылки


Пример 1: от A до Z

давайте сравним эти две модели: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] это то, что называется a отрицается класс символов: он соответствует чему угодно, но 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 матчей .* далее следует следующее выражение.

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