Python >> Tutoriel Python >  >> Python Tag >> RegEx

Opérateur d'échappement Python Regex \ dans les substitutions et les chaînes brutes

Tout d'abord,

replacement patterns ≠ regular expression patterns

Nous utilisons un modèle regex pour rechercher des correspondances, nous utilisons des modèles de remplacement pour remplacer les correspondances trouvées par regex.

REMARQUE  :Le seul caractère spécial dans un modèle de substitution est une barre oblique inverse , \ . Seul le backslash doit être doublé.

Syntaxe de modèle de remplacement en Python

Le re.sub les docs sont déroutantes car elles mentionnent les deux séquences d'échappement de chaîne qui peuvent être utilisées dans les modèles de remplacement (comme \n , \r ) et les séquences d'échappement regex (\6 ) et ceux qui peuvent être utilisés à la fois comme séquences d'échappement de regex et de chaîne (\& ).

J'utilise le terme séquence d'échappement regex pour désigner une séquence d'échappement composée d'une barre oblique inverse littérale + un caractère, c'est-à-dire '\\X' ou r'\X' , et une séquence d'échappement de chaîne pour désigner une séquence de \ et un caractère ou une séquence qui forment ensemble une séquence d'échappement de chaîne valide. Ils ne sont reconnus que dans les littéraux de chaîne normaux. Dans les littéraux de chaîne bruts, vous ne pouvez échapper que " (et c'est la raison pour laquelle vous ne pouvez pas terminer un littéral de chaîne brut avec \" , mais le jeu fait toujours partie de la chaîne alors).

Ainsi, dans un modèle de remplacement, vous pouvez utiliser des références arrière :

re.sub(r'\D(\d)\D', r'\1', 'a1b')    # => 1
re.sub(r'\D(\d)\D', '\\1', 'a1b')    # => 1
re.sub(r'\D(\d)\D', '\g<1>', 'a1b')  # => 1
re.sub(r'\D(\d)\D', r'\g<1>', 'a1b') # => 1

Vous pouvez voir que r'\1' et '\\1' est le même modèle de remplacement, \1 . Si vous utilisez '\1' , il sera analysé comme une séquence d'échappement de chaîne , un caractère de valeur octale 001 . Si vous oubliez d'utiliser r préfixe avec la référence arrière non ambiguë, il n'y a pas de problème car \g n'est pas une séquence d'échappement de chaîne valide, et là, \ caractère d'échappement reste dans la chaîne. Lisez les documents auxquels j'ai lié :

Contrairement au standard C, toutes les séquences d'échappement non reconnues restent inchangées dans la chaîne, c'est-à-dire que la barre oblique inverse est laissée dans le résultat.

Ainsi, lorsque vous dépassez '\.' comme chaîne de remplacement, vous envoyez en fait \. combinaison de deux caractères comme chaîne de remplacement, et c'est pourquoi vous obtenez \. dans le résultat.

\ est un caractère spécial dans le modèle de remplacement Python

Si vous utilisez re.sub(r'\s+\.', r'\\.', text) , vous obtiendrez le même résultat qu'en text2 et text3 cas, voir cette démo.

Cela se produit parce que \\ , deux barres obliques inverses littérales, désignent une seule barre oblique inverse dans le modèle de remplacement. Si vous n'avez pas de groupe 2 dans votre modèle regex, mais passez r'\2' dans le remplacement pour réellement remplacer par \ et 2 combinaison de caractères, vous obtiendrez une erreur.

Ainsi, lorsque vous avez des modèles de remplacement dynamiques définis par l'utilisateur, vous devez doubler toutes les barres obliques inverses dans les modèles de remplacement qui sont censés être transmis sous forme de chaînes littérales :

re.sub(some_regex, some_replacement.replace('\\', '\\\\'), input_string)

De la doc (mon emphase) :

re.sub(pattern, repl, string, count=0, flags=0) Renvoie la chaîne obtenue en remplaçant les occurrences les plus à gauche non superposées de pattern in string par le remplacement repl. Si le motif n'est pas trouvé, la chaîne est retournée inchangée. repl peut être une chaîne ou une fonction ; s'il s'agit d'une chaîne, tous les échappements antislash qu'elle contient sont traités. Autrement dit, \n est converti en un seul caractère de saut de ligne, \r est converti en un retour chariot, et ainsi de suite. Les échappements inconnus des lettres ASCII sont réservés pour une utilisation future et traités comme des erreurs. D'autres évasions inconnues telles que \&sont laissées seules. Les références arrière, telles que \6, sont remplacées par la sous-chaîne correspondant au groupe 6 dans le modèle.

Le rempl l'argument n'est pas simplement du texte brut. Il peut également s'agir du nom d'une fonction ou faire référence à une position dans un groupe (par exemple \g<quote> , \g<1> , \1 ).

Aussi, à partir d'ici :

Contrairement au standard C, toutes les séquences d'échappement non reconnues restent inchangées dans la chaîne, c'est-à-dire que la barre oblique inverse est laissée dans le résultat.

Depuis . n'est pas un caractère d'échappement spécial, '\.' est identique à r'\.\ .