Регулярное выражение Python - r префикс - PullRequest
62 голосов
/ 11 февраля 2010

Может кто-нибудь объяснить, почему работает приведенный ниже пример 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

Ответы [ 3 ]

69 голосов
/ 11 февраля 2010

Поскольку \ начинают 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 '\\'
\
31 голосов
/ 11 февраля 2010

«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 обрабатывает символы, которые не являются допустимыми управляющими символами, не все эти двойные обратные слэши необходимы - например, '\s'=='\\s', однако это не так для '\b' и '\\b'. Я предпочитаю быть явным и удваивать все обратные слеши.

5 голосов
/ 11 февраля 2010

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

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

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

...