Python的正则expression式前缀

任何人都可以解释为什么下面的例子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 

因为只有当它们是有效的转义序列时才开始转义序列。

 >>> '\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”前缀, 否则string中的转义序列将按照与标准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 

永远不要依赖原始string作为path文字,因为原始string有一些相当特殊的内部运作方式,已知在屁股上咬人:

当存在“r”或“R”前缀时,string中包含反斜杠后的字符不变,所有反斜杠都保留在string中。 例如,string文字r"\n"由两个字符组成:一个反斜杠和一个小写的“n”。 string引号可以使用反斜杠进行转义,但反斜杠保留在string中; 例如, r"\""是一个有效的string文字,由两个字符组成:反斜杠和双引号; r"\"不是有效的string文本(甚至原始string不能以奇数个反斜杠结尾)。具体来说,原始string不能以单个反斜杠结尾(因为反斜杠会转义下面的引号字符)。还要注意,一个反斜杠后跟一个换行符将被解释为string中的两个字符,而不是行延续。

为了更好地说明这一点:

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

'r'表示以下是“原始string”,即。 反斜杠字符被直接处理,而不是表示对以下字符的特殊处理。

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' '\b'也是如此'\\b' 。 我的意愿是明确的,并加倍所有的反斜杠。

不是所有涉及反斜杠的序列都是转义序列。 \t\f是,例如,但\s不是。 在非原始string文字中,任何不是转义序列的一部分的\被看作是另一个\

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

\b 一个转义序列,但是,例3失败。 (是的,有些人认为这种行为相当不幸。)