Échapper la chaîne d'expression régulière en Python

229

Je veux utiliser la saisie d'un utilisateur comme modèle d'expression régulière 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 un sens dans l'expression régulière? Par exemple, l'utilisateur souhaite rechercher Word (s): le moteur d'expression régulière prendra le en (s)tant que groupe. Je veux qu'il le traite comme une chaîne "(s)". Je peux exécuter replacesur l'entrée utilisateur et remplacer le (avec \(et le )avec \)mais le problème est que je devrai remplacer pour chaque symbole regex possible. Connaissez-vous un meilleur moyen?

MichaelT
la source

Réponses:

324

Utilisez la re.escape()fonction pour cela:

4.2.3 reContenu du module

escape (chaîne)

Chaîne de retour avec toutes les barres obliques inverses non alphanumériques; ceci est utile si vous souhaitez faire correspondre une chaîne littérale arbitraire qui peut contenir des métacaractères d'expression régulière.

Un exemple simpliste, recherchez toute occurrence de la chaîne fournie, éventuellement suivie de 's', et renvoyez l'objet de correspondance.

def simplistic_plural(word, text):
    word_or_plural = re.escape(word) + 's?'
    return re.match(word_or_plural, text)
ddaa
la source
53

Vous pouvez utiliser re.escape () :

re.escape (string) Chaîne de retour avec tous les caractères non alphanumériques rétro-obliques; ceci est utile si vous souhaitez faire correspondre une chaîne littérale arbitraire qui peut contenir des métacaractères d'expression régulière.

>>> import re
>>> re.escape('^a.*$')
'\\^a\\.\\*\\$'
gimel
la source
3

Malheureusement, re.escape()ne convient pas pour la chaîne de remplacement:

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

Une solution est de mettre le remplaçant dans un lambda:

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

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

Owen
la source
3
L' replargument de re.subest une chaîne, pas une expression régulière; l'appliquer re.escapen'a aucun sens en premier lieu.
tripleee
5
@tripleee C'est incorrect, l' replargument n'est pas une simple chaîne, il est analysé. Par exemple, re.sub(r'(.)', r'\1', 'X')reviendra X, non \1.
Flimm
4
Voici la question pertinente pour échapper à l' replargument: stackoverflow.com/q/49943270/247696
Flimm
3
Modifié dans la version 3.3: Le caractère '_' n'est plus échappé. Modifié dans la version 3.7: seuls les caractères qui peuvent avoir une signification spéciale dans une expression régulière sont échappés. (Pourquoi cela a-t-il pris autant de temps?)
Cees Timmerman