Limitación de la codicia en expresiones regulares en PHP
Las expresiones regulares son codiciosas por defecto. Esto significa que capturan la máxima cantidad posible de caracteres.
Analicemos con un ejemplo. Supongamos que tenemos la siguiente cadena:
<?php
$str = 'aeeex zzz x kkk';
?>
Supongamos que en esta cadena queremos encontrar la subcadena
'aeeex' con el siguiente patrón: letra
'a', luego cualquier carácter uno o más
veces, luego letra 'x'.
<?php
$res = preg_replace('#a.+x#', '!', $str);
?>
Esperamos que como resultado en la variable
se guarde la cadena '! zzz x kkk'. Sin embargo,
no es así - en la variable aparece la cadena
'! kkk'.
Todo se debe a que nuestra expresión regular busca todos
los caracteres desde la letra 'a' hasta la letra 'x'.
Pero en nuestra cadena hay dos letras 'x'. Debido
a la codicia, resulta que la expresión regular busca hasta
la última 'x', capturando así
algo diferente a lo que esperábamos.
Por supuesto, a menudo este comportamiento es exactamente el que necesitamos. Pero en este caso particular nos gustaría desactivar la codicia y decirle a la expresión regular que busque hasta la primera 'x'.
Para limitar la codicia, hay que poner el signo de interrogación después del operador de repetición:
<?php
$res = preg_replace('#a.+?x#', '!', $str);
?>
La codicia se puede limitar a todos los operadores
de repetición, de la siguiente manera: *?, ??
y {}?.
Se da la cadena:
<?php
$str = 'aba accca azzza wwwwa';
?>
Escriba una expresión regular que encuentre todas las cadenas
flanqueadas por letras 'a',
y reemplace cada una de ellas por '!'. Entre
las letras a puede haber cualquier carácter (excepto
'a').