Quantifiers
Los quantifiers solo se pueden aplicar a:
*
: Cero o más veces
+
: Una o más veces
?
: Cero o una vez
{3}
: Exactamente 3 veces
{3,}
: 3 o más veces
{3,6}
: Entre 3 y 6 veces
Los quantifiers greedy (avariciosos) hacen match de tantos caracteres como pueda:
Toma toda la cadena de entrada antes de intentar el primer match. Si el primer match falla (contra toda la cadena), el matcher se mueve un caracter hacia atrás (backtracking) y vuelve a intentar, repitiendo el proceso hasta encontrar el match o hasta que no haya más caracteres yendo hacia atrás.
a+
string: aaaaaaaaaa
hace match 1 vez.
.*foo
:
A greedy quantifier first matches as much as possible. So the .*
matches the ENTIRE STRING. Then the matcher tries to match the f following, but there are no characters left. So it "backtracks", making the greedy quantifier match one less thing (leaving the "o" at the end of the string unmatched). That still doesn't match the f in the regex, so it "backtracks" one more step, making the greedy quantifier match one less thing again (leaving the "oo" at the end of the string unmatched). That still doesn't match the f in the regex, so it backtracks one more step (leaving the "foo" at the end of the string unmatched). Now, the matcher finally matches the f in the regex, and the o and the next o are matched too. Success!
Los quantifiers reluctant hacen lo contrario: Comienzan al inicio de la cadena de entrada y van comiendo de uno en uno los caracteres hasta encontrar el match.
a+?
string: aaaaaaaaaa
hace match 10 veces
Explicación de .*?foo
:
A reluctant or "non-greedy" quantifier first matches as little as possible. So the .* matches nothing at first, leaving the entire string unmatched. Then the matcher tries to match the f following, but the unmatched portion of the string starts with "x" so that doesn't work. So the matcher backtracks, making the non-greedy quantifier match one more thing (now it matches the "x", leaving "fooxxxxxxfoo" unmatched). Then it tries to match the f, which succeeds, and the o and the next o in the regex match too. Success!
Los quantifiers possessive siempre se comen la cadena de entrada entera, intentan una vez (una y solo una vez) el match. A diferencia de los quantifiers greedy, estos quantifiers nunca van hacia atrás.
Explicación de: .*+foo
:
A possessive quantifier is just like the greedy quantifier, but it doesn't backtrack. So it starts out with .* matching the entire string, leaving nothing unmatched. Then there is nothing left for it to match with the f in the regex. Since the possessive quantifier doesn't backtrack, the match fails there.
Es probable que existan ambiguedades cuando se utilizan quantifiers y una expresión tiene varios operadores que hacen match contra un número variable de caracteres, por ejemplo:
Buscar una expresión regular que haga match de tags html, la expresión regular <.+>
pareciera la correcta sin embargo hará match del tag y de su contenido. Por ejemplo si se evalua <p>texto</p>
hará match TODA la cadena ya que .+
se comerá el primer >
y seguirá evaluándo caracteres hasta llegar a la última p
. La ambiguedad se puede corregir con el operador reluctant .+?
porque hace match únicamente de <p></p>
ya que .+?
se detiene en el primer >
.
La manera de prevenir ambiguedades es siendo más específico en los caracteres contra los que hacen match.