Python regex - préfixe r

87

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

# 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
JT.
la source

Réponses:

86

Parce que ne \commencent 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, les 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 un fonctionnement interne assez particulier , connu pour avoir mordu des gens dans le cul:

Lorsqu'un préfixe «r» ou «R» est présent, un caractère suivant une barre oblique inverse est inclus dans la chaîne sans changement et toutes les barres obliques inverses sont laissées dans la chaîne. Par exemple, la chaîne littérale se r"\n"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 une chaîne littérale valide composée 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 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,

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 '\\'
\
Esteban Küber
la source
En tant que correction mineure, '\s'(like r'\s') est également représenté comme '\\s', en raison de '\s'ne pas être une séquence d'échappement reconnue.
Massood Khaari
@MassoodKhaari Je jurerais que la sortie était correcte quand j'ai écrit cette réponse ... Corrigé.
Esteban Küber
1
8 ans justifient certainement le changement magique du comportement de python. : D
Massood Khaari
34

le 'r' signifie que ce qui suit est une "chaîne brute", ie. les caractères antislash sont traités littéralement au lieu de signifier un traitement spécial du caractère suivant.

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

il en '\n'va de même pour une seule nouvelle ligne
et contient r'\n'deux caractères - une barre oblique inverse et la lettre `` n '',
une autre façon de l'écrire serait '\\n'parce que la première barre oblique inverse échappe à la seconde

une manière é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'la même chose n'est pas vraie pour '\b'et '\\b'. Ma préférence est d'être explicite et de doubler toutes les barres obliques inverses.

John La Rooy
la source
5

Toutes les séquences impliquant des contre-obliques ne sont pas des séquences d'échappement. \tet \fsont, par exemple, mais \sne sont pas. Dans une chaîne littérale non brute, tout élément \qui ne fait pas partie d'une séquence d'échappement est considéré comme un autre \:

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

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

Thomas Wouters
la source
Exactement. Bien que, @JT, je recommande d'utiliser '\\ s' ou r '\ s', sinon vous frapperez probablement par inadvertance des séquences d'échappement que vous ne vouliez pas.
Blair Conrad
En effet: utilisez toujours des littéraux de chaîne bruts lorsque vous voulez que la chaîne contienne des barres obliques inverses (au lieu de vouloir réellement les séquences d'échappement.)
Thomas Wouters
@Thomas: réchappe encore certaines séquences lorsqu'elles apparaissent à la fin de la chaîne: r"\"n'est pas valide, pour ce faire, vous devez le faire "\\". Si vous le faites r"\\", vous obtenez une \\ ( "\\\\"chaîne) imprimée . Soyez prudent avec ça.
Esteban Küber
Oui, les littéraux de chaîne bruts ne peuvent pas se terminer par un seul `\`.
Thomas Wouters
@ Blair / Thomas: merci - c'était la règle générale que je suivais qui m'a confus en premier lieu! ... tout est clair maintenant, merci à tous. Bien qu'en suivant cette règle ... lors de la lecture du modèle à partir d'un fichier de texte brut, comment le modèle serait-il transmis en tant que chaîne littérale brute?
JT.
0

Essayez ça:

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

Vérifiez l'exemple ci-dessous:

print r"123\n123" 
#outputs>>>
123\n123


print "123\n123"
#outputs>>>
123
123
Ugur Umut
la source