Python建议在re
模块中定义正则表达式时使用原始字符串。来自Python documentation:
正则表达式使用反斜杠字符(' \')表示特殊表单或允许使用特殊字符而不调用其特殊含义。这与Python在字符串文字中用于相同目的的相同字符的使用相冲突;例如,要匹配文字反斜杠,可能必须写'' \\'作为模式字符串,因为正则表达式必须是\,并且每个反斜杠必须在常规Python字符串文字中表示为\。
但是,在许多情况下,这不是必需的,无论您是否使用原始字符串,都会得到相同的结果:
$ ipython
In [1]: import re
In [2]: m = re.search("\s(\d)\s", "a 3 c")
In [3]: m.groups()
Out[3]: ('3',)
In [4]: m = re.search(r"\s(\d)\s", "a 3 c")
In [5]: m.groups()
Out[5]: ('3',)
然而,在某些情况下情况并非如此:
In [6]: m = re.search("\s(.)\1\s", "a 33 c")
In [7]: m.groups()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-12-84a8d9c174e2> in <module>()
----> 1 m.groups()
AttributeError: 'NoneType' object has no attribute 'groups'
In [8]: m = re.search(r"\s(.)\1\s", "a 33 c")
In [9]: m.groups()
Out[9]: ('3',)
当你不使用原始字符串时,你必须转义特殊字符:
In [10]: m = re.search("\\s(.)\\1\\s", "a 33 c")
In [11]: m.groups()
Out[11]: ('3',)
我的问题是为什么非转义的非原始正则表达式字符串对特殊字符起作用(如上面的命令[2]中所述)?
答案 0 :(得分:8)
上面的示例有效,因为\s
和\d
不是python中的转义序列。根据文件:
与标准C不同,所有未识别的转义序列都保留在字符串中不变,即反斜杠保留在字符串中。
但是最好只使用原始字符串,而不是担心python转义是什么或不是什么,或者担心如果你改变正则表达式后来改变它。
答案 1 :(得分:6)
这是因为\s
和\d
不是转义序列:
>>> print('\s')
\s
>>> print('\d')
\d
>>>
因此,它们被视为\s
和\d
。 \1
但是转义序列:
>>> print('\1')
☺
>>>
这意味着它被解释为☺
而不是\1
。
有关Python转义序列的完整列表,请参阅文档中的String and Bytes literals。