对正则表达式中的反斜杠感到困惑

时间:2015-11-07 11:21:24

标签: python regex

我对正则表达式中的反斜杠感到困惑。在正则表达式中,\具有特殊含义,例如\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'>

有人有解释吗?

3 个答案:

答案 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