我对正则表达式中的反斜杠感到困惑。在正则表达式中,\
具有特殊含义,例如\d
表示十进制数字。如果在反斜杠前添加反斜杠,则此特殊含义会丢失。在regex-howto可以阅读:
也许最重要的元字符是反斜杠,
\
。与Python字符串文字一样,反斜杠后面可以跟各种字符,以指示各种特殊序列。它也用于转义所有元字符,因此您仍然可以在模式中匹配它们;例如,如果您需要匹配[
或\
,则可以在它们前面加上反斜杠以删除其特殊含义:\[
或\\
。
所以print(re.search('\d', '\d'))
给出None
,因为\d
匹配任何十进制数字,但\d
中没有。
我现在希望print(re.search('\\d', '\d'))
与\d
匹配,但答案仍为None
。
仅print(re.search('\\\d', '\d'))
作为输出<_sre.SRE_Match object; span=(0, 2), match='\\d'>
。
有人有解释吗?
答案 0 :(得分:13)
混淆是由于反斜杠字符\
被用作两个不同级别的转义。首先,Python解释器本身在\
模块看到你的字符串之前为re
执行替换。例如,\n
转换为换行符,\t
转换为制表符,等等。要获得实际的\
字符,您也可以将其转义,因此{{ 1}}给出一个\\
个字符。如果\
后面的字符不是已识别的转义字符,则\
会被视为任何其他字符并通过,但我不建议这取决于此。相反,请务必将\
字符翻倍,即\
。
如果你想看看Python如何扩展你的字符串转义,只需打印出字符串即可。例如:
\\
如果s = 'a\\b\tc'
print s
是汇总数据类型的一部分,例如列表或元组,如果打印该聚合,Python会将字符串括在单引号中并包含s
转义符(以规范形式),因此请注意字符串的打印方式。如果你只是在解释器中输入一个带引号的字符串,它也会用引号括起来用&#39; \&#39;逃逸。
一旦你知道你的字符串是如何被编码的,你就可以考虑\
模块将对它做什么。例如,如果要在传递给re
模块的字符串中转义\
,则需要将re
传递给\\
,这意味着您需要在引用的Python字符串中使用re
。 Python字符串最终会以\\\\
结尾,\\
模块会将其视为单个文字re
字符。
在Python字符串中包含\
个字符的另一种方法是使用原始字符串,例如\
相当于r'a\b'
。
答案 1 :(得分:7)
对search()的调用中正则表达式之前的r字符指定正则表达式是原始字符串。这允许反斜杠在正则表达式中用作常规字符,而不是在转义字符序列中。让我解释一下......
在re模块的搜索方法处理传递给它的字符串之前,Python解释器对字符串进行初始传递。如果字符串中存在反斜杠,则Python解释器必须确定每个是否是Python转义序列的一部分(例如\ n或\ t)。
注意:此时Python并不关心&#39; \&#39;是一个正则表达式元字符。
如果&#39; \&#39;后跟一个公认的Python转义字符(t,n等),然后反斜杠和转义字符将替换为实际的Unicode或8位字符。例如,&#39; \ t&#39;将替换为选项卡的ASCII字符。否则它会被传递并解释为&#39; \&#39;字符。
请考虑以下事项。
>>> s = '\t'
>>> print ("[" + s + "]")
>>> [ ] // an actual tab character after preprocessing
>>> s = '\d'
>>> print ("[" + s + "]")
>>> [\d] // '\d' after preprocessing
有时我们希望在字符串中包含一个包含&#39; \&#39;没有它被Python解释为转义序列。要做到这一点,我们逃避了&#39; \&#39;与&#39; \#39;。现在,当Python看到&#39; \&#39;它用一个&#39; \&#39;替换了两个反斜杠。字符。
>>> s = '\\t'
>>> print ("[" + s + "]")
>>> [\t] // '\t' after preprocessing
在Python解释器对两个字符串进行传递后,它们将被传递给re模块的搜索方法。 search方法解析正则表达式字符串以标识正则表达式的元字符。
现在&#39; \&#39;也是一个特殊的正则表达式元字符,并且被解释为一个在执行re search()方法时被转义的UNLESS。
考虑以下电话。
>>> match = re.search('a\\t','a\\t') //Match is None
此处匹配为无。为什么?让我们看看Python解释器传递后的字符串。
String 1: 'a\t'
String 2: 'a\t'
那么为什么匹配等于None?当search()解释String 1时,由于它是正则表达式,因此反斜杠被解释为元字符,而不是普通字符。但是,字符串2中的反斜杠不在正则表达式中,并且已由Python解释器处理,因此它被解释为普通字符。
所以search()方法正在寻找一个转义&#39;在字符串&#39; a \ t&#39;这不是匹配。
要解决此问题,我们可以告诉search()方法不解释&#39; \&#39;作为一个元字符。我们可以通过逃避它来做到这一点。
考虑以下电话。
>>> match = re.search('a\\\\t','a\\t') // Match contains 'a\t'
再次,让我们看看Python解释器传递后的字符串。
String 1: 'a\\t'
String 2: 'a\t'
现在,当search()方法处理正则表达式时,它会看到第一个反斜杠被第一个反斜杠转义,不应该被视为元字符。因此,它将字符串解释为&#39; a \ t&#39;,它与字符串2匹配。
另一种让search()考虑&#39; \&#39;作为一个字符是在正则表达式之前放置一个r。这告诉Python解释器不要预处理字符串。
考虑一下。
>>> match = re.search(r'a\\t','a\\t') // match contains 'a\t'
这里Python解释器不会修改第一个字符串,但会处理第二个字符串。传递给search()的字符串是:
String 1: 'a\\t'
String 2: 'a\t'
与前面的示例一样,搜索解释了&#39; \&#39;作为单个字符&#39; \&#39;而不是元字符,因此与字符串2匹配。
答案 2 :(得分:4)
Python自己的字符串解析(部分)以您的方式进行。
如果您想查看re
看到的内容,请输入
print '\d'
print '\\d'
print '\\\d'
在Python命令提示符下。您看到\d
和\\d
都导致\d
,后者由Python字符串解析器处理。
如果您想避免任何麻烦,请按照re module documentation的建议使用原始字符串:r'\\d'
会导致RE模块看到\\d
。