W3docs

Quantificadores Gulosos e Preguiçosos

Aprenda como funcionam os quantificadores gulosos e preguiçosos em expressões regulares JavaScript: o modo guloso consome o máximo e retrocede, enquanto o preguiçoso (*?, +?, ??, {n,m}?) usa o mínimo. Com exemplos executáveis.

Um quantificador como *, + ou ? indica a uma expressão regular quantas vezes o padrão anterior pode se repetir. Mas quando diferentes comprimentos de texto podem satisfazer o padrão, o motor precisa decidir qual deles usar. É essa decisão que os quantificadores gulosos e preguiçosos controlam.

Por padrão, todo quantificador é guloso: ele captura o máximo de caracteres possível. Adicione um ? após o quantificador e ele se torna preguiçoso: captura o mínimo possível. Escolher o modo errado é um dos erros mais comuns em regex — o sintoma clássico é um padrão que "corresponde a mais do que deveria." Esta página explica o mecanismo por trás de ambos os modos para que você possa escolher o certo de forma deliberada.

Como o modo guloso realmente funciona: consumir e depois retroceder

Um quantificador guloso não sabe magicamente onde parar. Ele funciona em duas fases:

  1. Consumir o máximo. .* primeiro engole todo o restante da string.
  2. Retroceder. Se o padrão que segue .* não puder mais corresponder (porque tudo já foi consumido), o motor devolve caracteres um de cada vez, tentando novamente após cada um, até que todo o padrão se encaixe.

Portanto, guloso significa "pegar tudo, e depois reluctantemente devolver o mínimo necessário para que o restante do padrão tenha sucesso." Compreender a etapa de retrocesso é a chave para prever o comportamento de padrões gulosos.

* guloso em ação


javascript— editable

Aqui .* corresponde a qualquer caractere zero ou mais vezes. Como não há nada obrigatório após ele, nenhum retrocesso é necessário e ele mantém tudo até o fim da linha, produzindo "ABCD*E".

+ guloso em ação


javascript— editable

C+ corresponde a "C" uma ou mais vezes e, de forma gulosa, captura os três, então a correspondência é "ABCCC".

Como o modo preguiçoso funciona: consumir o mínimo e depois expandir

Um quantificador preguiçoso inverte a estratégia:

  1. Consumir o mínimo. .*? começa correspondendo a nada.
  2. Expandir. Somente se o restante do padrão não conseguir corresponder é que o motor deixa o quantificador preguiçoso capturar um caractere a mais, e então tenta novamente — repetindo até que todo o padrão seja satisfeito.

Portanto, preguiçoso significa "pegar o mínimo possível e crescer somente quando forçado." Você torna qualquer quantificador preguiçoso acrescentando ?.

*? preguiçoso em ação


javascript— editable

Este é o caso confuso. O resultado é apenas "AB". Por quê? Porque .*? tem permissão de corresponder a nada, e não há nada após ele no padrão que force mais consumo. Assim que AB corresponde, o padrão já está completo, então o quantificador preguiçoso para felizmente com zero caracteres. Um quantificador preguiçoso só se expande quando algo após ele — um delimitador, um literal ou uma âncora — exige isso.

+? preguiçoso em ação


javascript— editable

C+? deve corresponder a pelo menos um "C" (é isso que + exige), e nada após ele pede mais, então ele para no primeiro: "ABC".

O exemplo canônico: <.*> vs <.*?>

A diferença entre guloso e preguiçoso é mais fácil de ver quando algo após o quantificador. A correspondência de tags HTML é o caso clássico. Execute ambos os padrões na mesma string:


javascript— editable
  • Guloso /<.*>/ corresponde a "<p>Hello</p>" — a string inteira. .* consume tudo, depois retrocede apenas o suficiente para deixar um > para o > final no padrão, parando no último >.
  • Preguiçoso /<.*?>/ corresponde apenas a "<p>" — uma única tag. .*? se expande caractere por caractere e para no instante em que encontra o primeiro >.

Quando seu objetivo é "corresponder a uma tag," "corresponder a uma string entre aspas" ou "corresponder até o próximo delimitador," o modo preguiçoso é quase sempre o que você quer.

A família completa de quantificadores preguiçosos

Todo quantificador guloso tem um par preguiçoso formado pela adição de ?:

GulosoPreguiçosoSignificado da forma preguiçosa
**?Zero ou mais, o mínimo possível
++?Um ou mais, o mínimo possível
???Zero ou um, prefere zero
{2,5}{2,5}?Entre 2 e 5, prefere 2
{2,}{2,}?Pelo menos 2, prefere 2

Note que ?? não é um erro de digitação: o primeiro ? é o quantificador (zero ou um) e o segundo o torna preguiçoso, portanto ele prefere não corresponder a nada quando tem escolha.


javascript— editable

Quando usar quantificadores preguiçosos?

Uma regra prática:

Use um quantificador preguiçoso quando quiser corresponder até a primeira ocorrência de um delimitador, e o guloso quando quiser tudo até o último.

Situações comuns em que o modo preguiçoso é a escolha certa:

  • Extrair uma única tag HTML/XML: /<.*?>/.
  • Capturar o conteúdo de um par de aspas ou colchetes: /".*?"/, /\(.*?\)/.
  • Capturar texto até o próximo separador sem avançar para o registro seguinte.

Dois avisos importantes:

  • Um delimitador costuma ser mais claro do que a preguiça. Em vez de /".*?"/ você pode escrever /"[^"]*"/ com uma classe de caracteres negada. Isso evita o retrocesso totalmente e geralmente é mais rápido e previsível.
  • O modo preguiçoso precisa de algo para parar. Como o exemplo AB.*? mostrou, um quantificador preguiçoso no final de um padrão (sem nada que o force adiante) colapsa ao mínimo e corresponde a quase nada. Combine-o com um literal seguinte, uma âncora ou um grupo de captura.

Resumo

  • Os quantificadores são gulosos por padrão — eles tomam o máximo e depois retrocedem para que o restante do padrão se encaixe.
  • Acrescente ? para tornar um quantificador preguiçoso — ele toma o mínimo e só expande quando forçado.
  • Um quantificador preguiçoso sem nada após ele corresponde ao mínimo que pode legalmente (muitas vezes nada), então sempre forneça um delimitador ou âncora para que ele pare.
  • A família completa de preguiçosos é *?, +?, ?? e {n,m}?.
  • Use o modo preguiçoso quando quiser "até o primeiro" delimitador; caso contrário, uma classe de caracteres negada costuma ser a escolha mais limpa e rápida.

Prática

Prática
Dada a string '<p>Hi</p>', o que o padrão preguiçoso /<.*?>/ corresponde?
Dada a string '<p>Hi</p>', o que o padrão preguiçoso /<.*?>/ corresponde?
Was this page helpful?