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