Lookahead e Lookbehind Positivo e Negativo nas Expressões Regulares do Python
Às vezes, é necessário resolver um problema deste tipo:
encontrar a string 'aaa' e substituí-la
por '!', mas somente se depois de
'aaa' houver 'x', e o próprio
'x' não deve ser substituído. Se tentarmos
resolver o problema 'de maneira direta',
não teremos sucesso:
txt = 'aaax baaa'
res = re.sub('aaax', '!', txt)
print(res) # exibirá '! baaa', mas queríamos '!x baaa'
Lookahead
Para resolver o problema, é necessária uma maneira de dizer
que 'x' não deve ser substituído. Isto é feito
usando colchetes especiais (?= ),
que apenas verificam, mas não consomem os caracteres.
Estes colchetes são chamados de lookahead positivo.
Positivo - porque 'x'
(no nosso caso) deve estar presente - somente então
a substituição ocorrerá.
Vamos aplicar estes colchetes para resolver nosso problema:
txt = 'aaax baaa'
res = re.sub('aaa(?=x)', '!', txt)
print(res) # exibirá '!x aaab
Existe também o lookahead negativo
- (?! ) - que, ao contrário, diz
que algo não deve estar presente. No próximo
exemplo, a substituição ocorrerá somente se
depois de 'aaa' NÃO houver 'x':
txt = 'aaax aaab'
res = re.sub('aaa(?!x)', '!', txt)
print(res) # exibirá 'aaax !b'
Lookbehind
Da mesma forma, existe o lookbehind positivo
- (?<= ). No
próximo exemplo, a substituição ocorrerá somente
se antes de 'aaa' houver 'x':
txt = 'xaaa'
res = re.sub('(?<=x)aaa', '!', txt)
print(res) # exibirá 'x!'
E também existe o lookbehind negativo
- (?<! ). No próximo exemplo
a substituição ocorrerá somente se antes de
'aaa' NÃO houver 'x':
txt = 'baaa'
res = re.sub('(?<!x)aaa', '!', txt)
print(res) # exibirá 'b!'
Problemas Práticos
Dada uma string contendo nomes de funções:
txt = 'func1() func2() func3()'
Obtenha um array com os nomes das funções a partir da string.
Dada uma string com uma tag:
txt = '<a href="" class="eee" id="zzz">'
Obtenha um array com os nomes dos atributos desta tag.
Dada uma string com variáveis:
txt = '$aaa $bbb $ccc xxxx'
Obtenha as substrings que são precedidas pelo símbolo de cifrão.