Lookahead et lookbehind positifs et négatifs dans les regex Python
Parfois, il faut résoudre un problème de ce type :
trouver la chaîne 'aaa' et la remplacer
par '!', mais seulement si après
'aaa' se trouve 'x', et ne pas
remplacer 'x' lui-même. Si nous
essayons de résoudre le problème 'directement',
nous n'y arriverons pas :
txt = 'aaax baaa'
res = re.sub('aaax', '!', txt)
print(res) # affichera '! baaa', alors que nous voulions '!x baaa'
Lookahead
Pour résoudre le problème, il faut un moyen de dire
que 'x' ne doit pas être remplacé. Cela
se fait à l'aide de parenthèses spéciales (?= ),
qui vérifient simplement sans consommer les caractères.
Ces parenthèses sont appelées lookahead positif.
Positif - car 'x'
(dans notre cas) doit être présent - alors seulement
le remplacement aura lieu.
Utilisons ces parenthèses pour résoudre notre problème :
txt = 'aaax baaa'
res = re.sub('aaa(?=x)', '!', txt)
print(res) # affichera '!x aaab
Il existe aussi le lookahead négatif
- (?! ) - il dit, au contraire,
que quelque chose ne doit pas être présent. Dans l'exemple
suivant, le remplacement aura lieu seulement si
après 'aaa' il n'y a PAS 'x' :
txt = 'aaax aaab'
res = re.sub('aaa(?!x)', '!', txt)
print(res) # affichera 'aaax !b'
Lookbehind
De manière analogue, il existe le lookbehind
positif - (?<= ). Dans
l'exemple suivant, le remplacement aura lieu seulement
si avant 'aaa' se trouve 'x' :
txt = 'xaaa'
res = re.sub('(?<=x)aaa', '!', txt)
print(res) # affichera 'x!'
Et il existe aussi le lookbehind négatif
- (?<! ). Dans l'exemple suivant
le remplacement aura lieu, seulement si avant
'aaa' ne se trouve pas 'x' :
txt = 'baaa'
res = re.sub('(?<!x)aaa', '!', txt)
print(res) # affichera 'b!'
Problèmes pratiques
Soit une chaîne contenant des noms de fonctions :
txt = 'func1() func2() func3()'
Obtenez un tableau des noms de fonctions à partir de la chaîne.
Soit une chaîne avec une balise :
txt = '<a href="" class="eee" id="zzz">'
Obtenez un tableau des noms des attributs de cette balise.
Soit une chaîne avec des variables :
txt = '$aaa $bbb $ccc xxxx'
Obtenez les sous-chaînes précédées du symbole dollar.