反斜杠的麻烦
在早期规定中,正则表达式用反斜杠字符 ("\") 来表示特殊格式或允许使用特殊字符而不调用它的特殊用法。这就与 Python 在字符串中的那些起相同作用的相同字符产生了冲突。
让我们举例说明,你想写一个 RE 以匹配字符串 "\section",可能是在一个 LATEX 文件查找。为了要在程序代码中判断,首先要写出想要匹配的字符串。接下来你需要在所有反斜杠和其它元字符前加反斜杠来取消其特殊意义,结果要匹配的字符串就成了"\section"。 当把这个字符串传递给re.compile()时必须还是"\section"。然而,作为Python的字符串实值(string literals)来表示的话,"\section"中两个反斜杠还要再次取消特殊意义,最后结果就变成了"\\section"。
字符 | 阶段 |
---|---|
\section | 要匹配的字符串 |
\section | 为 re.compile 取消反斜杠的特殊意义 |
"\\section" | 为"\section"的字符串实值(string literals)取消反斜杠的特殊意义 |
简单地说,为了匹配一个反斜杠,不得不在 RE 字符串中写 '\\',因为正则表达式中必须是 "\",而每个反斜杠在常规的 Python 字符串实值中必须表示成 "\"。在 REs 中反斜杠的这个重复特性会导致大量重复的反斜杠,而且所生成的字符串也很难懂。
解决的办法就是为正则表达式使用 Python 的 raw 字符串表示;在字符串前加个 "r" 反斜杠就不会被任何特殊方式处理,所以 r"\n" 就是包含"\" 和 "n" 的两个字符,而 "\n" 则是一个字符,表示一个换行。正则表达式通常在 Python 代码中都是用这种 raw 字符串表示。
常规字符串 | Raw 字符串 |
---|---|
"ab*" | r"ab*" |
"\\section" | r"\section" |
"\w+\s+\1" | r"\w+\s+\1" |