Controlando a ganância em expressões regulares no Python
As expressões regulares são, por padrão, gananciosas. Isso significa que elas capturam a quantidade máxima possível de caracteres. Vamos analisar um exemplo. Suponha que temos a seguinte string:
txt = 'aeeex zzz x kkk'
Nesta string, queremos encontrar a substring
'aeeex' usando o seguinte padrão:
letra 'a', seguida por qualquer caractere
uma ou mais vezes, seguida pela letra 'x':
res = re.sub('a.+x', '!', txt)
print(res)
Embora esperássemos obter a string '! zzz
x kkk', será impressa a string '! kkk'.
Tudo se deve ao fato de que nossa regex busca
todos os caracteres da letra 'a' até a letra
'x'. Mas na nossa string existem duas letras
'x'! Devido à ganância, a regex busca
até o último 'x',
acabando por capturar não o que precisávamos.
Claro, muitas vezes esse comportamento é exatamente o que desejamos. Mas, neste caso específico, precisamos desativar a ganância e dizer à regex para buscar apenas até o primeiro 'x'. Para isso, devemos colocar um ponto de interrogação após o operador de repetição:
res = re.sub('a.+?x', '!', txt)
print(res) # irá imprimir a string '! zzz x kkk'
A ganância pode ser controlada para todos os operadores
de repetição: tanto *, quanto ?, e
{} - desta forma: *?, ??
e {}?.
Dada a string:
txt = 'aba accca azzza wwwwa'
Escreva uma expressão regular que encontre todas as
strings que possuem a letra
'a' nas extremidades, e substitua cada uma delas por
'!'. Entre as letras 'a' pode
haver qualquer caractere (exceto 'a').