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


87

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

Ответы:


86

Потому что \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 '\\'
\

В качестве незначительного исправления '\s'(подобное r'\s') также отображается как '\\s', поскольку '\s'не является распознанной escape-последовательностью.
Massood Khaari 05

@MassoodKhaari Клянусь, вывод был правильным, когда я писал этот ответ ... Исправлено.
Эстебан Кюбер,

1
8 лет, безусловно, оправдывают волшебные изменения в поведении питонов. : D
Massood Khaari

34

'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'. Я предпочитаю быть явным и удваивать все обратные косые черты.


5

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

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

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


В яблочко. Хотя, @JT, я рекомендую использовать '\\ s' или r '\ s', иначе вы, вероятно, случайно столкнетесь с некоторыми escape-последовательностями, которых не хотели.
Блэр Конрад,

В самом деле: всегда используйте необработанные строковые литералы, когда вы хотите, чтобы строка содержала обратную косую черту (в отличие от фактического использования escape-последовательностей.)
Томас Воутерс,

@Thomas: по- rпрежнему экранирует некоторые последовательности, когда они появляются в конце строки: r"\"недействительно, для этого вам нужно сделать это "\\". Если вы это сделаете r"\\", вы получите \\ напечатанную ( "\\\\"строку). Будьте осторожны с этим.
Эстебан Кюбер,

Да, необработанные строковые литералы не могут заканчиваться одним символом `\`.
Томас Воутерс,

@ Блэр / Томас: спасибо - это было общее правило, которому я следовал, и оно в первую очередь запутало меня! ... теперь все ясно, спасибо всем. Хотя, следуя этому правилу ... при чтении шаблона из простого текстового файла, как шаблон будет передан как необработанная буквальная строка?
JT.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.