Resumo : neste tutorial, você aprenderá sobre o modo guloso de regex e como ele afeta a maneira como os quantificadores procuram correspondências.
O problema com o modo ganancioso de regex
Suponha que você tenha a seguinte string:
<a href="/" title="Go to homepage">Home</a>
Linguagem de código: PHP ( php )
E você deseja combinar o texto entre aspas ( ""
). Para fazer isso, você pode usar o seguinte padrão que inclui a classe de caracteres.
ponto ( ) e o quantificador ( ) :+
".+"
Linguagem de código: PHP ( php )
O significado do padrão é o seguinte:
"
começa com uma citação.
corresponde a qualquer caractere, exceto a nova linha+
corresponde ao caractere uma ou mais vezes"
termina com a citação
O seguinte usa a preg_match_all()
função para encontrar uma correspondência na string com o padrão:
<?php
$str = '<a href="/" title="Go to the homepage">Home</a>';
$pattern = '/".+"/';
if (preg_match_all($pattern, $str, $matches)) {
print_r($matches);
}
Linguagem de código: PHP ( php )
Ele retorna o seguinte:
Array
(
[0] => "/" title="Go to the homepage"
)
Linguagem de código: PHP ( php )
Este resultado não é o que você esperava.
A razão é que o quantificador ( +
) usa o modo ganancioso por padrão. No modo guloso, o quantificador ( +
) tenta corresponder ao seu elemento anterior (um caractere) tantas vezes quanto possível.
Vamos entender como funciona o modo guloso de regex.
Entenda como funciona o modo guloso de regex
Para combinar o $str
com o $pattern
, o mecanismo regex corresponderá a todas as posições no $str
começando $pattern
na primeira posição da string.
Portanto, o mecanismo regex inicia a partir do primeiro caractere do arquivo $str
. Como é o <
que não corresponde à aspa ( "
) no padrão, o mecanismo regex continua a pesquisar até atingir a primeira aspa ( "
) na string:
O mecanismo regex analisa o padrão e combina a string com a próxima regra .+
. Como a .+
regra corresponde a um caractere uma ou mais vezes, o mecanismo regex corresponde a todos os caracteres até chegar ao final da string:
O mecanismo regex examina a última regra do padrão, que é uma aspa (“).
Porém, já chega ao final da string. Não há mais personagem para combinar. Foi muito ganancioso para ir longe demais.
Portanto, o mecanismo regex volta do final da string para encontrar a aspa (“). Isso é chamado de retrocesso:
Como resultado, a correspondência é a seguinte substring que não é o que você esperava:
"/" title="Go to homepage"
Linguagem de código: PHP ( php )
Por padrão, outros quantificadores também usam o modo ganancioso. Para corrigir esse problema, você precisa transformar o modo ganancioso em um modo não ganancioso (ou preguiçoso), adicionando um ponto de interrogação ( ?
) ao quantificador como este:
".+?"
Linguagem de código: PHP ( php )
O código a seguir retorna o resultado esperado:
<?php
$str = '<a href="/" title="Go to the homepage">Home</a>';
$pattern = '/".+?"/';
if (preg_match_all($pattern, $str, $matches)) {
print_r($matches[0]);
}
Linguagem de código: PHP ( php )
Saída:
Array
(
[0] => "/"
[1] => "Go to the homepage"
)
Linguagem de código: PHP ( php )
Para entender como funciona o modo regex não-ganancioso , confira o tutorial regex não-ganancioso .
Resumo
- Por padrão, os quantificadores usam o modo ganancioso.
- Um quantificador ganancioso tenta corresponder ao seu elemento anterior tantas vezes quanto possível.