web-dev-qa-db-fra.com

Python regex - préfixe r

Quelqu'un peut-il expliquer pourquoi l'exemple 1 ci-dessous fonctionne, lorsque le préfixe r n'est pas utilisé? Je pensais que le préfixe r devait être utilisé chaque fois que des séquences d'échappement étaient utilisées. L'exemple 2 et l'exemple 3 en témoignent.

# example 1
import re
print (re.sub('\s+', ' ', 'hello     there      there'))
# prints 'hello there there' - not expected as r prefix is not used

# example 2
import re
print (re.sub(r'(\b\w+)(\s+\1\b)+', r'\1', 'hello     there      there'))
# prints 'hello     there' - as expected as r prefix is used

# example 3
import re
print (re.sub('(\b\w+)(\s+\1\b)+', '\1', 'hello     there      there'))
# prints 'hello     there      there' - as expected as r prefix is not used
64
JT.

Car \ ne commence les séquences d'échappement que lorsqu'elles sont des séquences d'échappement valides.

>>> '\n'
'\n'
>>> r'\n'
'\\n'
>>> print '\n'


>>> print r'\n'
\n
>>> '\s'
'\\s'
>>> r'\s'
'\\s'
>>> print '\s'
\s
>>> print r'\s'
\s

sauf si un préfixe 'r' ou 'R' est présent, séquences d'échappement dans les chaînes sont interprétées selon des règles similaires à celles utilisées par la norme C. Les séquences d'échappement reconnues sont:

Escape Sequence   Meaning Notes
\newline  Ignored  
\\    Backslash (\)    
\'    Single quote (')     
\"    Double quote (")     
\a    ASCII Bell (BEL)     
\b    ASCII Backspace (BS)     
\f    ASCII Formfeed (FF)  
\n    ASCII Linefeed (LF)  
\N{name}  Character named name in the Unicode database (Unicode only)  
\r    ASCII Carriage Return (CR)   
\t    ASCII Horizontal Tab (TAB)   
\uxxxx    Character with 16-bit hex value xxxx (Unicode only) 
\Uxxxxxxxx    Character with 32-bit hex value xxxxxxxx (Unicode only) 
\v    ASCII Vertical Tab (VT)  
\ooo  Character with octal value ooo
\xhh  Character with hex value hh

Ne vous fiez jamais aux chaînes brutes pour les littéraux de chemin, car les chaînes brutes ont des fonctionnements internes plutôt particuliers , connus pour avoir mordu des gens dans le cul:

Lorsqu'un préfixe "r" ou "R" est présent, un caractère qui suit une barre oblique inverse est inclus dans la chaîne sans modification et toutes les barres obliques inverses sont laissées dans la chaîne. Par exemple, la chaîne littérale r"\n" se compose de deux caractères: une barre oblique inverse et un "n" minuscule. Les guillemets de chaîne peuvent être échappés avec une barre oblique inverse, mais la barre oblique inverse reste dans la chaîne; par exemple, r"\"" est un littéral de chaîne valide composé de deux caractères: une barre oblique inverse et un guillemet double; r"\" n'est pas un littéral de chaîne valide (même une chaîne brute ne peut pas se terminer par un nombre impair de barres obliques inverses). Plus précisément, une chaîne brute ne peut pas se terminer par une seule barre oblique inverse (car la barre oblique inverse échapperait au caractère de guillemet suivant). Notez également qu'une seule barre oblique inverse suivie d'une nouvelle ligne est interprétée comme ces deux caractères dans le cadre de la chaîne, et non comme une continuation de ligne.

Pour mieux illustrer ce dernier point:

>>> r'\'
SyntaxError: EOL while scanning string literal
>>> r'\''
"\\'"
>>> '\'
SyntaxError: EOL while scanning string literal
>>> '\''
"'"
>>> 
>>> r'\\'
'\\\\'
>>> '\\'
'\\'
>>> print r'\\'
\\
>>> print r'\'
SyntaxError: EOL while scanning string literal
>>> print '\\'
\
69
Esteban Küber

le "r" signifie que ce qui suit est une "chaîne brute", c'est-à-dire. les barres obliques inverses sont traitées littéralement au lieu de signifier un traitement spécial pour le caractère suivant.

http://docs.python.org/reference/lexical_analysis.html#literals

alors '\n' est une seule nouvelle ligne
et r'\n' est composé de deux caractères - une barre oblique inverse et la lettre 'n'
une autre façon de l'écrire serait '\\n' car la première barre oblique inverse échappe à la seconde

une façon équivalente d'écrire ceci

print (re.sub(r'(\b\w+)(\s+\1\b)+', r'\1', 'hello     there      there'))

est

print (re.sub('(\\b\\w+)(\\s+\\1\\b)+', '\\1', 'hello     there      there'))

En raison de la façon dont Python traite les caractères qui ne sont pas des caractères d'échappement valides, toutes ces doubles barres obliques inverses ne sont pas nécessaires - par exemple '\s'=='\\s' mais il n'en va pas de même pour '\b' et '\\b'. Ma préférence est d'être explicite et de doubler toutes les barres obliques inverses.

31
John La Rooy

Toutes les séquences impliquant des barres obliques inverses ne sont pas des séquences d'échappement. \t et \f le sont, par exemple, mais \s n'est pas. Dans un littéral de chaîne non brut, tout \ qui ne fait pas partie d'une séquence d'échappement n'est considéré que comme un autre \:

>>> "\s"
'\\s'
>>> "\t"
'\t'

\bis une séquence d'échappement, cependant, donc l'exemple 3 échoue. (Et oui, certaines personnes considèrent ce comportement plutôt malheureux.)

5
Thomas Wouters

Essayez ça:

a = '\''
'
a = r'\''
\'
a = "\'"
'
a = r"\'"
\'
0
user2856064