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
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 '\\'
\
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.
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'
\b
is une séquence d'échappement, cependant, donc l'exemple 3 échoue. (Et oui, certaines personnes considèrent ce comportement plutôt malheureux.)
Essayez ça:
a = '\''
'
a = r'\''
\'
a = "\'"
'
a = r"\'"
\'