为什么\ *即使是原始字符串也会逃脱?

时间:2014-06-05 03:40:07

标签: python regex

我读过“当' r'如果存在前缀,则字符串中包含反斜杠后面的字符不会更改,并且所有反斜杠都保留在字符串中。但是当我创建一个正则表达式对象:p=re.compile(r'\*(.*?)\*')时,它匹配'*text*'。我不明白为什么会这样。根据我的印象,它应与'\*text\*'匹配。

1 个答案:

答案 0 :(得分:12)

正则表达式专门处理反斜杠。反斜杠禁用*等特殊字符的“魔术”行为。

要实际匹配反斜杠,您需要在原始字符串中添加两个:r'\\foo'

我觉得让你感到困惑的是,反斜杠在字符串中是特殊的,对于正则表达式也是特殊的。 Python有原始字符串来简化你的生活:在原始字符串中,反斜杠并不特殊,让你可以自由地思考实际正则表达式处理反斜杠的特殊方式。

正则表达式编译器将看到这个包含两个字符的序列:\*

它会看到反斜杠,并删除反斜杠并特别处理*(禁用“魔法”)。

如果您使用原始字符串,则可以轻松创建两个字符的序列:r'\*'

但是如果你没有使用原始字符串,那么反斜杠在字符串中是特殊的,所以你需要加倍反斜杠来得到一个:'\\*'

s = '\\*'
assert len(s) == 2
assert s[0] == '\\'
assert s[1] == '*'

如果你真的想匹配模式\*,那么你需要一个反斜杠后跟另一个反斜杠,以获得实际反斜杠的匹配;然后是反斜杠后跟*,以获得实际*的匹配。

p = re.compile(r'\\\*')
assert p.search(r'\*')

关于原始字符串中的反斜杠有两个特殊规则,两者结合在一起:反斜杠可以转义引号字符,因此您不能以奇数个反斜杠结束原始字符串。

https://docs.python.org/2/faq/design.html#why-can-t-raw-strings-r-strings-end-with-a-backslash

编辑:@Charles Duffy指出Python的re模块提供了一个函数,可以正确地“转义”特殊字符,以便在您想要完全匹配它们的时候。

import re
s_pat = re.escape(r'*text*')
assert s_pat[0] == '\\'
assert s_pat[1] == '*'

如果您希望同时匹配文字*并使用*的特殊行为,则可以采用以下方法:

s_pat = '(' + re.escape(r'*text*') + ')*'

这是一种匹配零个或多个实际字符串*text*

的模式