web-dev-qa-db-fra.com

Échappement de la chaîne regex dans Python

Je souhaite utiliser les entrées d'un utilisateur en tant que motif regex pour une recherche sur du texte. Cela fonctionne, mais comment puis-je gérer les cas où l'utilisateur met des caractères qui ont une signification dans regex? Par exemple, l'utilisateur souhaite rechercher Word (s): Le moteur d'expression régulière prend le groupe (s). Je veux qu'il traite comme une chaîne "(s)". Je peux exécuter replace sur une entrée utilisateur et remplacer le ( Par \( Et le ) Par \), Mais le problème est qu'il me faudra faire pour remplacer pour chaque symbole de regex possible. Connaissez-vous un meilleur moyen?

203
MichaelT

Utilisez la fonction re.escape() pour cela:

4.2.3 re Contenu du module

échappe (chaîne)

Renvoie une chaîne avec tous les caractères non alphanumériques inversés; Cela est utile si vous souhaitez faire correspondre une chaîne littérale arbitraire pouvant contenir des métacaractères d'expression régulière.

Un exemple simpliste, recherchez n'importe quelle occurrence de la chaîne fournie éventuellement suivie de 's', et retournez l'objet correspondant.

def simplistic_plural(Word, text):
    Word_or_plural = re.escape(Word) + 's?'
    return re.match(Word_or_plural, text)
283
ddaa

Vous pouvez utiliser re.escape () :

re.escape (string) Renvoie une chaîne avec tous les caractères non alphanumériques inversés; Cela est utile si vous souhaitez faire correspondre une chaîne littérale arbitraire pouvant contenir des métacaractères d'expression régulière.

>>> import re
>>> re.escape('^a.*$')
'\\^a\\.\\*\\$'
51
gimel

Malheureusement, re.escape() n'est pas adapté à la chaîne de remplacement:

>>> re.sub('a', re.escape('_'), 'aa')
'\\_\\_'

Une solution consiste à mettre le remplacement dans un lambda:

>>> re.sub('a', lambda _: '_', 'aa')
'__'

parce que la valeur de retour du lambda est traitée par re.sub() comme une chaîne littérale.

2
Owen