Python 为什么\*即使是原始字符串也会转义?

Python 为什么\*即使是原始字符串也会转义?,python,regex,Python,Regex,我已经读到,当出现“r”前缀时,反斜杠后面的字符将包含在字符串中而不作任何更改,并且所有反斜杠都保留在字符串中。但是当我创建一个regex对象时:p=re.compile(r'\*(.*?\*),它匹配'*text*'。我不明白为什么会这样。在我看来,它应该匹配“\*text\*”正则表达式专门处理反斜杠。反斜杠禁用特殊字符的“魔法”行为,如* p = re.compile(r'\\\*') assert p.search(r'\*') 要真正匹配反斜杠,需要在原始字符串中放入两个:r'\\f

我已经读到,当出现“r”前缀时,反斜杠后面的字符将包含在字符串中而不作任何更改,并且所有反斜杠都保留在字符串中。但是当我创建一个regex对象时:
p=re.compile(r'\*(.*?\*)
,它匹配
'*text*'
。我不明白为什么会这样。在我看来,它应该匹配
“\*text\*”

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

p = re.compile(r'\\\*')
assert p.search(r'\*')
要真正匹配反斜杠,需要在原始字符串中放入两个:
r'\\foo'

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

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

它将看到反斜杠,删除反斜杠,并专门处理
*
(禁用“魔法”)

如果您使用的是原始字符串,则很容易创建两个字符的序列:
r'\*'

s = '\\*'
assert len(s) == 2
assert s[0] == '\\'
assert s[1] == '*'
但是,如果不使用原始字符串,反斜杠在字符串中是特殊的,因此需要将反斜杠加倍才能得到一个:
“\\*”

s = '\\*'
assert len(s) == 2
assert s[0] == '\\'
assert s[1] == '*'
如果您确实想要匹配模式
\*
,则需要一个反斜杠,后跟另一个反斜杠,以获得实际反斜杠上的匹配;然后是一个反斜杠,后跟一个
*
,以获得实际
*
上的匹配项

p = re.compile(r'\\\*')
assert p.search(r'\*')
关于原始字符串中的反斜杠,有两条特殊规则,这两条规则一起使用:反斜杠可以转义引号字符,因此不能以奇数个反斜杠结束原始字符串

编辑:@charlesduffy指出,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*

+1:这里没有介绍的唯一有用的相关内容是
re.escape()
(提供一个人们可以用来找出如何匹配给定字符串的通用工具);如果你能扩展你的回答,我很乐意删除我的答案。@steveha谢谢你的解释,但是我仍然有一个关于原始字符串的问题,我想你可能会有所帮助。