Python 正则表达式 - r 前缀
有没有人能解释一下,为什么下面的示例1在没有使用r
前缀的情况下也能正常工作?我原以为只要使用了转义序列,就必须加上r
前缀。示例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
5 个回答
并不是所有带有反斜杠的序列都是转义序列。比如,\t
和 \f
是转义序列,但 \s
不是。在非原始字符串中,任何不属于转义序列的 \
都被视为普通的 \
:
>>> "\s"
'\\s'
>>> "\t"
'\t'
不过,\b
是一个转义序列,所以例子 3 失败了。(是的,有些人觉得这种行为挺不方便的。)
这里的'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'
就不一样了。我个人更喜欢明确地把所有反斜杠都写成双的。
因为\
只有在它是有效的转义序列时才会开始转义。
>>> '\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' 的前缀,否则字符串中的转义序列会按照类似于标准C语言的规则来解释。被识别的转义序列包括:
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 '\\'
\