Estou tentando dividir uma string em duas partes usando regex. A sequência é formatada da seguinte maneira:
text to extract<number>
Eu tenho usado (.*?)<
e <(.*?)>
que funciona bem, mas depois de ler um pouco sobre regex, comecei a me perguntar por que preciso ?
das expressões. Eu só fiz isso depois de encontrá-los neste site, então não sei exatamente qual é a diferença.
regex
regex-greedy
non-greedy
Doug
fonte
fonte
Respostas:
É a diferença entre quantificadores gananciosos e não gananciosos.
Considere a entrada
101000000000100
.Usar
1.*1
,*
é ganancioso - ele corresponderá até o fim e depois voltará até que possa corresponder1
, deixando você com1010000000001
..*?
não é ganancioso.*
não corresponderá a nada, mas tentará corresponder caracteres extras até corresponder1
, eventualmente correspondendo101
.Todos os quantificadores têm um modo não-ganancioso:
.*?
,.+?
,.{2,6}?
, e mesmo.??
.No seu caso, um padrão semelhante poderia ser
<([^>]*)>
- corresponder a qualquer coisa, exceto um sinal de maior que (estritamente falando, ele corresponde a zero ou mais caracteres que não sejam>
intermediários<
e>
).Consulte Folha de dicas do quantificador .
fonte
?
difere do não-ganancioso??
?"abc"
, o regex/\w\w?\w/
corresponderia à sequência completa"abc"
- porque?
é ganancioso./\w\w??\w/
é preguiçoso - ele só corresponde"ab"
. Ele só retornará e corresponderá"abc"
se falhar mais tarde.Em ganancioso vs não ganancioso
A repetição na regex, por padrão, é gananciosa : eles tentam corresponder o máximo de repetições possível e, quando isso não funciona e precisam voltar, tentam corresponder a menos um representante de cada vez, até que uma correspondência de todo o padrão seja encontrado. Como resultado, quando uma partida finalmente acontece, uma repetição gananciosa corresponderá ao maior número possível de representantes.
O
?
quantificador de repetição muda esse comportamento para não ganancioso , também chamado de relutante ( em Java, por exemplo ) (e às vezes "preguiçoso"). Em contraste, esta repetição vai primeiro tentar igualar como alguns representantes quanto possível, e quando isso não funciona e eles têm que voltar atrás, eles começam a correspondência mais uma rept um tempo. Como resultado, quando uma partida finalmente acontece, uma repetição relutante corresponderia ao menor número de repetições possível.Referências
Exemplo 1: de A a Z
Vamos comparar esses dois padrões:
A.*Z
eA.*?Z
.Dada a seguinte entrada:
Os padrões produzem as seguintes correspondências:
A.*Z
produz 1 partida:AiiZuuuuAoooZ
( veja em rubular.com )A.*?Z
produz 2 correspondências:AiiZ
eAoooZ
( veja em rubular.com )Vamos primeiro nos concentrar no que
A.*Z
faz. Quando combinou com o primeiroA
, o.*
, sendo ganancioso, primeiro tenta combinar o maior número.
possível.Como
Z
não corresponde, o mecanismo retorna e.*
deve corresponder a menos um.
:Isso acontece mais algumas vezes, até que finalmente chegamos a isso:
Agora
Z
pode corresponder, portanto, o padrão geral corresponde:Por outro lado, a repetição relutante nos
A.*?Z
primeiros jogos corresponde ao.
mínimo possível e, em seguida, leva o.
máximo que for necessário. Isso explica por que ele encontra duas correspondências na entrada.Aqui está uma representação visual do que os dois padrões corresponderam:
Exemplo: uma alternativa
Em muitas aplicações, as duas correspondências na entrada acima são o que se deseja, portanto, um relutante
.*?
é usado no lugar do ganancioso.*
para evitar a superação. Para esse padrão específico, no entanto, existe uma alternativa melhor, usando a classe de caracteres negada.O padrão
A[^Z]*Z
também encontra as mesmas duas correspondências que oA.*?Z
padrão para a entrada acima ( como visto em ideone.com ).[^Z]
é o que é chamado de classe de caracteres negada : corresponde a qualquer coisa, menosZ
.A principal diferença entre os dois padrões está no desempenho: sendo mais rigorosa, a classe de caracteres negados pode corresponder apenas a um caminho para uma determinada entrada. Não importa se você usa modificador ganancioso ou relutante para esse padrão. De fato, em alguns sabores, você pode se sair ainda melhor e usar o que é chamado de quantificador possessivo, que não retrocede.
Referências
Exemplo 2: de A a ZZ
Este exemplo deve ser ilustrativo: mostra como os padrões de classe de caracteres gananciosos, relutantes e negados são diferentes de acordo com a mesma entrada.
Estas são as correspondências para a entrada acima:
A[^Z]*ZZ
produz 1 partida:AuuZZ
( como visto em ideone.com )A.*?ZZ
produz 1 partida:AiiZooAuuZZ
( como visto em ideone.com )A.*ZZ
produz 1 partida:AiiZooAuuZZeeeZZ
( como visto em ideone.com )Aqui está uma representação visual do que eles corresponderam:
tópicos relacionados
Esses são links para perguntas e respostas no stackoverflow que cobrem alguns tópicos que podem ser do seu interesse.
Uma repetição gananciosa pode superar outra
fonte
Digamos que você tenha:
<(.*)>
corresponderiaa></a
onde como<(.*?)>
corresponderiaa
. O último pára após a primeira partida de>
. Ele verifica se há uma ou 0 correspondências.*
seguidas pela próxima expressão.A primeira expressão
<(.*)>
não para quando corresponde à primeira>
. Continuará até a última partida de>
.fonte