Python regex - r префикс

Может кто-нибудь объяснить, почему пример 1 ниже работает, когда префикс r не используется? Я думал, что префикс r должен использоваться всякий раз, когда используются escape-последовательности. Пример 2 и пример 3 демонстрируют это.

# 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

Ответ 1

Потому что \ начинают escape-последовательности только тогда, когда они являются действительными escape-последовательностями.

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


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

Если нет префикса 'r' или 'R', escape-последовательности в строках интерпретируются в соответствии с правилами, аналогичными тем, которые используются в стандарте C. Распознаются escape-последовательности:

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

Никогда не полагайтесь на необработанные строки для литералов пути, так как необработанные строки имеют довольно своеобразную внутреннюю работу, которая, как известно, укусила людей в заднице:

При наличии префикса "r" или "R" символ, следующий за обратной косой чертой, включается в строку без изменений, и все обратные косые черты остаются в строке. Например, строковый литерал r"\n" состоит из двух символов: обратной косой черты и строчной буквы "n". Строковые кавычки можно экранировать с помощью обратной косой черты, но обратная косая черта остается в строке; например, r"\"" является допустимым строковым литералом, состоящим из двух символов: обратной косой черты и двойной кавычки; r"\" не является допустимым строковым литералом (даже необработанная строка не может заканчиваться нечетным числом обратных косых черт). В частности, необработанная строка не может заканчиваться одним обратным слешем (так как обратный слеш будет экранировать следующий символ кавычки). Также обратите внимание, что одиночная обратная косая черта, за которой следует новая строка, интерпретируется как эти два символа как часть строки, а не как продолжение строки.

Чтобы лучше проиллюстрировать этот последний пункт:

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

Ответ 2

"r" означает следующее: "необработанная строка", т.е. символы обратной косой черты обрабатываются буквально, а не означают специальную обработку следующего символа.

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

поэтому '\n' является одной новой строкой
и r'\n' - два символа - обратная косая черта и буква "n"
другой способ записать это будет '\\n', потому что первая обратная косая черта ускользает от второго

эквивалентный способ записи этого

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

является

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

Из-за того, как Python обрабатывает символы, которые не являются допустимыми escape-символами, не все эти двойные обратные косые черты необходимы - например, '\s'=='\\s', однако это не так для '\b' и '\\b'. Мое предпочтение должно быть явным и удвоить все обратные косые черты.

Ответ 3

Не все последовательности с обратными косыми чертами являются escape-последовательностями. \t и \f, например, но \s нет. В неровном строковом литерале любой \, который не является частью escape-последовательности, рассматривается как просто еще один \:

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

\b - это escape-последовательность, поэтому пример 3 не выполняется. (И да, некоторые считают это поведение весьма неудачным.)

Ответ 4

Попробуйте это:

a = '\''
'
a = r'\''
\'
a = "\'"
'
a = r"\'"
\'

Ответ 5

Проверьте ниже пример:

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


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