为什么正则表达式的“非捕获”组不工作?
在下面的代码片段中,非捕获组 "(?:aaa)"
应该在匹配结果中被忽略,
所以结果应该只有 "_bbb"
。
但是,我得到的匹配结果却是 "aaa_bbb"
;只有当我指定 group(2) 时,它才会显示 "_bbb"
。
>>> import re
>>> s = "aaa_bbb"
>>> print(re.match(r"(?:aaa)(_bbb)", s).group())
aaa_bbb
7 个回答
TFM:
class re.MatchObject
group([group1, ...])
这个方法可以返回匹配结果中的一个或多个子组。如果你只给它一个参数,它会返回一个字符串;如果你给它多个参数,它会返回一个包含每个参数对应结果的元组。如果不传任何参数,默认返回的是第一个组(也就是整个匹配的内容)。如果你传入的参数是零,那么返回的就是整个匹配的字符串。
我觉得你对“非捕获组”的概念有些误解。非捕获组匹配的内容仍然会成为整个正则表达式匹配的一部分。
正则表达式 (?:aaa)(_bbb)
和 (aaa)(_bbb)
都会返回 aaa_bbb
作为整体匹配结果。它们的区别在于,第一个正则表达式有一个捕获组,会返回 _bbb
作为匹配结果,而第二个正则表达式有两个捕获组,分别返回 aaa
和 _bbb
作为匹配结果。在你的Python代码中,要获取 _bbb
,你需要用第一个正则表达式的 group(1)
,而用第二个正则表达式则需要 group(2)
。
非捕获组的主要好处是,你可以把它们添加到正则表达式中,而不会影响捕获组的编号。而且,它们在性能上也稍微好一些,因为正则引擎不需要跟踪非捕获组匹配的文本。
如果你真的想把 aaa
从整体正则匹配中排除,那你需要使用前后查找。在这种情况下,正向前查找就能解决问题:(?<=aaa)_bbb
。使用这个正则表达式时,group()
在Python中会返回 _bbb
,不需要捕获组。
我的建议是,如果你可以使用捕获组来获取正则匹配的一部分,最好还是用这种方法,而不是使用前后查找。
group()
和 group(0)
会返回整个匹配的结果。后面的组才是真正的捕获组。
>>> print (re.match(r"(?:aaa)(_bbb)", string1).group(0))
aaa_bbb
>>> print (re.match(r"(?:aaa)(_bbb)", string1).group(1))
_bbb
>>> print (re.match(r"(?:aaa)(_bbb)", string1).group(2))
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: no such group
如果你想要和 group()
一样的效果,可以这样做:
" ".join(re.match(r"(?:aaa)(_bbb)", string1).groups())