Limitación de la avaricia en expresiones regulares en Python
Las expresiones regulares son por defecto avaras. Esto significa que capturan la máxima cantidad posible de caracteres. Analicemos con un ejemplo. Supongamos que tenemos la siguiente cadena:
txt = 'aeeex zzz x kkk'
En esta cadena queremos encontrar la subcadena
'aeeex' usando el siguiente patrón:
letra 'a', luego cualquier carácter
una o más veces, luego letra 'x':
res = re.sub('a.+x', '!', txt)
print(res)
Aunque esperamos obtener la cadena '! zzz
x kkk', se mostrará la cadena '! kkk'.
El problema es 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 avaricia, resulta que
la expresión regular busca hasta la última 'x',
capturando así algo diferente a lo que necesitábamos.
Por supuesto, a menudo este comportamiento es precisamente el que requerimos. Pero en este caso específico necesitamos desactivar la avaricia y decirle a la expresión regular que busque hasta la primera 'x'. En este caso, debemos colocar un signo de interrogación después del operador de repetición:
res = re.sub('a.+?x', '!', txt)
print(res) # mostrará la cadena '! zzz x kkk'
La avaricia se puede limitar a todos los operadores
de repetición: tanto *, como ?, y
{} - de esta manera: *?, ??
y {}?.
Se da la cadena:
txt = 'aba accca azzza wwwwa'
Escriba una expresión regular que encuentre todas
las cadenas en cuyos extremos hay letras
'a', y reemplace cada una de ellas por
'!'. Entre las letras 'a' puede
haber cualquier carácter (excepto 'a').