Quantificadores
Os quantificadores determinam a quantidade permitida do item que eles precedem. Há 3 tipos de quantificadores: gulosos, preguiçosos e possessivos.
Quantificadores gulosos
Os quantificadores gulosos são chamados assim porque casam com o máximo de caracteres possível. Veja quais são eles:
-
?
: esse quantificador torna o item que o precede opcional. Exemplos:ciou?
(casa com ciou e cio),ci[eo]?
(casa com cie, cio e ci) ees(tr|en)?
(casa com estr, esen e es). -
*
: é chamado de estrela/asterisco. Pode casar 0 ou mais vezes com o item que o precede. Exemplos:err*
(casa com er, err, errrrrrr) egrande am.*
(casa com grande amor, grande amigo que você fez nas férias). -
+
: é bem semelhante ao*
. A diferença é que o item anterior a esse quantificador precisa estar presente pelo menos uma vez. Exemplos:err+
(casa com err, errrrrr, mas não com er),es+
(casa com es, esssss),e(r|s|a)+
(casa com er, essa, era) ep([aeiou]|r)+
(casa com pro, par, pai). -
Intervalo: algumas engines também suportam esse quantificador. Ele especifica, entre chaves, o número mínimo
de vezes que o item anterior pode aparecer, e, opcionalmente, o número máximo também. Há 3 sintaxes:
{min}
,{min,}
e{min,max}
. Há engines que suportam esse quantificador, mas suportam apenas a primeira sintaxe. Exemplos desse quantificador:r{1}
(casa apenas com r),[aeiou]{2,}
(casa com ai, ou, ei, aeuaeiuo),[0-9]{2,3}
(casa com 390, 52) e[0-9]{4,5}-?[0-9]{4,4}
(casa com um telefone celular do Brasil sem DDD. Casa tanto com telefones no formato 9999-9999, como também com telefones no formato 99999-9999).
Quantificadores preguiçosos
Os quantificadores preguiçosos tem os mesmos tipos de quantificadores que os gulosos. A diferença é que eles são
expressos com um ? à frente do quantificador: *?
, +?
, ??
e
{x,y}?
.
Ao contrário dos quantificadores gulosos, os preguiçosos casam com o mínimo de caracteres possível. Esses quantificadores são um pouco difíceis de entender. Por isso, vou explicá-los de uma maneira mais detalhada.
Vamos supor que você tenha na sua string a palavra zoológico. Se você usar a expressão regular
zo*
, ela vai casar com zoo, porque você usou um quantificador guloso. Mas, se você usar
zo*?
, ela vai casar apenas com z, porque o quantificador exige que ela case com o item
anterior 0 ou mais vezes, e como ele é preguiçoso, ele vai casar com o mínimo possível. Agora, se você usar
zo*?lógico
, ele vai casar com a palavra zoológico.
Veja que, no último exemplo, o quantificador preguiçoso casou com dois caracteres, o máximo que dava pra casar. Isso porque, se ele não fizesse isso, ele ia deixar de casar com a palavra zoológico. E pra casar com alguma coisa na string, qualquer quantificador preguiçoso abre mão da preguiça. É uma preguiça responsável :)
Outros exemplos de quantificadores preguiçosos: rou??
(casa com ro), rou??pa
(casa com roupa), rou+?
(casa com rou), zo+?.*o
(casa com zoo,
zoológico), re{1,}?.*r
(casa com reinar, reerguer),
.*(dor|eira)+?
(casa com assento de madeira, limpador).
Quantificadores possessivos
Há também os quantificadores possessivos. Para falar sobre eles, primeiramente é preciso explicar algo que ocorre muito durante a interpretação de expressões regulares, que se chama backtracking.
Vamos supor que temos uma string com o conteúdo durante os nossos dias e a expressão regular
.*e
. Ela casa com a palavra durante. Temos na expressão regular um quantificador guloso e o
caractere literal e. O quantificador guloso casa com o durant. Mas isso não ocorre logo no início.
Em um primeiro momento, o quantificador guloso casa com tudo, porque ele casa com o máximo de caracteres
possível que atendam as suas condições. No caso, é a string toda. Só que aí, ele não consegue casar com o
restante da expressão regular, que no caso é o e
.
Quando a expressão regular falha e há um quantificador guloso que poderia casar com menos caracteres, esse quantificador cede um caractere. Esse processo é chamado de backtracking. Ele é feito sempre com um caractere por vez. Isso é feito porque a expressão regular não tem a inteligência de saber "de primeira" qual é o máximo de caracteres que podem casar com um quantificador guloso sem que a expressão regular falhe.
O quantificador guloso casa com o máximo de caracteres possível e cede caracteres para a engine quando ela precisar e enquanto eles puderem ceder. No exemplo citado, o quantificador guloso vai ceder caracteres até ficar apenas com durant. Quando isso ocorre, a expressão regular passa, então ela não precisa pedir mais caracteres ao quantificador.
Perceba que os quantificadores sempre cedem apenas um caractere por vez, para não correr o risco de ceder mais do que o necessário, já que eles são quantificadores gulosos, e como bons gulosos, querem comer o máximo de caracteres que puderem, mas sem deixar de cooperar com a engine.
O backtracking não acontece apenas com o quantificador estrela. Ocorre com qualquer quantificador guloso, enquanto ele puder ceder caracteres para que a expressão regular case com alguma coisa.
O backtracking também pode ocorrer em alternações. A engine para de interpretar alternativas de uma alternação depois que ela casa com alguma delas. Então, se eu tiver três alternativas e a engine casar logo na primeira, as outras duas são ignoradas.
Caso a expressão regular falhe, a engine faz o backtracking para analisar ramificações que não foram testadas,
pois talvez as outras também casem e façam a expressão regular inteira casar. Exemplo: limi(t|ta)do
(casa com limitado. Note que, a princípio, a engine casa com a primeira alternativa da alternação. Só
que, como o restante da expressão regular não casa, ela testa a segunda alternativa, que faz a expressão regular
casar).
Quantificadores possessivos são muito parecidos com quantificadores gulosos. A diferença é que eles não fazem backtracking. Por isso, eles são chamados de possessivos. Os gulosos colaboram com a engine. Os possessivos não colaboram. Eles nunca cedem caracteres para a engine.
Quantificadores possessivos tem os mesmos tipos de quantificadores que os gulosos. A diferença é que cada
quantificador tem um + no final dele: *+
, ++
, ?+
e
{x,y}+
. Exemplos: .*+o
(não casa com nada, porque o quantificador casa com tudo e não
faz backtracking), .*a*+o
(casa com limitado, achado, lixeiro. Perceba que em
todos esses exemplos o quantificador possessivo não casa com nada), (re|se)?+.*te
(casa com
repelente, serpente, reagente, sete).
Muitas vezes, usar um quantificador possessivo pode fazer com que expressões regulares falhem porque ele não faz o backtracking. Sendo assim, você pode pensar que não faz sentido usar esse quantificador. Pra que usá-lo se ele pode fazer a expressão falhar? Em alguns casos, pode valer a pena, porque ele tem um desempenho melhor. Como ele não permite o backtracking, a engine não perde o tempo dela com isso. Mas, como você pode ver, é um pouco mais complexo e menos natural formular expressões regulares com ele. Geralmente, não é bom usá-lo.