2010-02-11 21 views
37

¿Alguien puede explicar por qué funciona el siguiente ejemplo 1, cuando no se utiliza el prefijo r? Pensé que el prefijo r debe usarse siempre que se usen secuencias de escape. Ejemplo 2 y el ejemplo 3 demuestra este ..Python regex - r prefijo

# 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 

Respuesta

55

Debido \ comenzar secuencias de escape sólo cuando son secuencias de escape válidos.

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


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

Unless una 'r' o prefijo 'R' está presente, escape sequences en las cadenas son interpretados de acuerdo con normas similares a los utilizados por Standard C. Las secuencias de escape reconocidos son:

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 

Nunca confíe en las cadenas sin formato para los literales de ruta, ya que las cadenas sin formato tienen algunas funciones internas peculiares, que se sabe que han mordido a las personas en el culo:

Cuando hay un prefijo "r" o "R" presente, un carácter que sigue a una barra invertida se incluye en la cadena sin cambios, y todas las barras invertidas quedan en la cadena. Por ejemplo, el literal de cadena r"\n" consta de dos caracteres: una barra diagonal inversa y una "n" minúscula. Las comillas de cadena se pueden escapar con una barra diagonal inversa, pero la barra invertida permanece en la cadena; por ejemplo, r"\"" es un literal de cadena válido que consta de dos caracteres: una barra diagonal inversa y una comilla doble; r"\" no es un literal de cadena válido (incluso una cadena en bruto no puede terminar en un número impar de barras invertidas). Específicamente, una cadena sin formato no puede terminar en una sola barra invertida (ya que la barra invertida escaparía al siguiente carácter de comillas). Tenga en cuenta también que una sola barra invertida seguida de una línea nueva se interpreta como esos dos caracteres como parte de la cadena, no como una continuación de línea.

Para mejor ilustrar este último punto:

>>> 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 '\\' 
\ 
4

No todas las secuencias que implican barras invertidas son secuencias de escape. \t y \f son, por ejemplo, pero \s no lo es. En una cadena no prima literal, cualquier \ que no es parte de una secuencia de escape se ve simplemente como otro \:

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

\bes una secuencia de escape, sin embargo, por lo que el ejemplo 3 falla. (Y sí, algunas personas consideran este comportamiento bastante desafortunado).

+0

Exactamente. Aunque, @JT, recomiendo usar '\\ s' o r '\ s', o probablemente golpearás inadvertidamente algunas secuencias de escape que no pretendías. –

+0

De hecho: utilice siempre cadenas crudas literales cuando desee que la cadena contenga barras invertidas (en lugar de querer realmente las secuencias de escape). –

+0

@Thomas: 'r' todavía escapa de algunas secuencias cuando aparecen al final de la cadena:' r "\" 'no es válido, para hacer eso tienes que hacer' "\\" '. Si haces 'r" \\ "', obtienes un '\\' impreso ('" \\\\ "' cadena). Ten cuidado con eso – voyager

21

la 'r' significa que la siguiente es una "cadena en bruto", es decir. los caracteres de barra invertida son tratados literalmente en lugar de significar un trato especial para el siguiente personaje.

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

por lo '\n' es un solo salto de línea
y r'\n' es dos personajes - una barra invertida y la letra 'n'
otra manera de escribir que sería '\\n' porque la primera barra invertida se escapa el segundo

una manera equivalente de escribir este

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

es

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

Debido a la forma de Python trata caracteres que no son válidos los caracteres de escape, no todas esas barras invertidas dobles son necesarias - por ejemplo '\s'=='\\s' sin embargo, el mismo no es cierto para '\b' y '\\b'. Mi preferencia es ser explícito y doblar todas las barras diagonales inversas.