Я пытаюсь разделить строку на две части с помощью регулярных выражений. Строка отформатирована следующим образом:
text to extract<number>
Я использовал (.*?)<
и <(.*?)>
которые работают хорошо, но после небольшого прочтения регулярных выражений, я просто начал задумываться, зачем мне нужны ?
выражения. Я сделал это только после того, как нашел их на этом сайте, поэтому я не совсем уверен, в чем разница.
Ответы:
Это разница между жадными и не жадными квантификаторами.
Рассмотрим вход
101000000000100
.Использование
1.*1
,*
жадный - он будет соответствовать до конца, а затем возвращаться, пока не совпадет1
, оставляя вас с1010000000001
..*?
не жадный*
ничего не будет соответствовать, но затем будет пытаться сопоставить дополнительные символы, пока они не совпадут1
, в конечном итоге совпадения101
.Все кванторы имеют режим , не жадный:
.*?
,.+?
,.{2,6}?
, и даже.??
.В вашем случае подобный шаблон мог бы быть
<([^>]*)>
- совпадать с чем угодно, кроме знака больше чем (строго говоря, он соответствует нулю или большему количеству символов, кроме>
промежуточных<
и>
).См. Шпаргалку квантификатора .
источник
?
отличается от не жадного??
?"abc"
, регулярное выражение/\w\w?\w/
будет соответствовать полной строке"abc"
- потому что?
это жадный./\w\w??\w/
ленивый - он будет только соответствовать"ab"
. Он будет возвращаться и совпадать только в"abc"
случае неудачи позже.На жадных против не жадных
Повторение в регулярном выражении по умолчанию является жадным : они пытаются сопоставить столько повторений, сколько возможно, и, когда это не работает, и им приходится возвращаться назад, они пытаются соответствовать одному меньшему количеству повторений за раз, пока совпадение всего шаблона не будет нашел. В результате, когда совпадение наконец произойдет, жадное повторение будет соответствовать как можно большему количеству повторений.
?
Как повторение Квантор изменяет это поведение в нежадным , называемый также неохотно ( в , например , Java ) (а иногда и «ленивый»). Напротив, это повторение сначала будет пытаться сопоставить как можно меньше повторений, и когда это не сработает, и они должны вернуться назад, они начинают сопоставлять еще одно повторение за раз. В результате, когда совпадение, наконец, происходит, неохотное повторение будет соответствовать как можно меньшему количеству повторений.Ссылки
Пример 1: от А до Я
Давайте сравним эти две модели:
A.*Z
иA.*?Z
.Учитывая следующий вход:
Шаблоны дают следующие совпадения:
A.*Z
дает 1 матч:AiiZuuuuAoooZ
( см. на rubular.com )A.*?Z
дает 2 совпадения:AiiZ
иAoooZ
( см. на rubular.com )Давайте сначала сосредоточимся на том, что
A.*Z
делает. Когда это соответствует первомуA
, то.*
, будучи жадным, сначала пытается сопоставить.
как можно больше.Поскольку
Z
не совпадает, двигатель возвращается назад и.*
должен соответствовать одному меньшему.
:Это происходит еще несколько раз, пока, наконец, мы не придем к этому:
Теперь
Z
может совпадать, поэтому общий шаблон соответствует:Напротив, повторение неохотно
A.*?Z
вначале соответствует.
как можно меньшему количеству, а затем принимает больше.
при необходимости. Это объясняет, почему он находит два совпадения на входе.Вот наглядное представление о том, что два шаблона совпали:
Пример: альтернатива
Во многих приложениях два совпадения в приведенном выше вводе - это то, что является желательным, поэтому
.*?
вместо жадности используется неохотное средство,.*
чтобы предотвратить чрезмерное совпадение. Однако для этого конкретного шаблона есть лучшая альтернатива, использующая класс отрицанных символов.Шаблон
A[^Z]*Z
также находит те же два совпадения, что иA.*?Z
шаблон для вышеуказанного ввода ( как видно на ideone.com ).[^Z]
это то, что называется отрицательным символьным классом : он соответствует чему угодно, кромеZ
.Основное различие между этими двумя шаблонами заключается в производительности: будучи более строгим, класс отрицанных символов может соответствовать только одному способу для данного ввода. Не имеет значения, используете ли вы жадный или неохотный модификатор для этого шаблона. На самом деле, в некоторых разновидностях вы можете сделать еще лучше и использовать так называемый притяжательный квантификатор, который вообще не возвращается.
Ссылки
Пример 2: от A до ZZ
Этот пример должен быть иллюстративным: он показывает, как жадные, неохотные и отрицательные шаблоны классов символов по-разному совпадают при одном и том же вводе.
Это совпадения для вышеуказанного ввода:
A[^Z]*ZZ
дает 1 совпадение:AuuZZ
( как видно на ideone.com )A.*?ZZ
дает 1 совпадение:AiiZooAuuZZ
( как видно на ideone.com )A.*ZZ
дает 1 совпадение:AiiZooAuuZZeeeZZ
( как видно на ideone.com )Вот визуальное представление того, что они совпали:
похожие темы
Это ссылки на вопросы и ответы по stackoverflow, которые охватывают некоторые темы, которые могут представлять интерес.
Одно жадное повторение может перерасти другое
источник
Допустим, у вас есть:
<(.*)>
будет соответствоватьa></a
там, где<(.*?)>
будет соответствоватьa
. Последний останавливается после первого матча>
. Он проверяет одно или 0 совпадений, за.*
которым следует следующее выражение.Первое выражение
<(.*)>
не останавливается при сопоставлении с первым>
. Это будет продолжаться до последнего матча>
.источник