Python正则(?:...)非捕获组在re.match与re.findall下行为差异疑问
非捕获组在
re.match与re.findall中行为一致的本质原因 核心前提:非捕获组的定义从未变化
非捕获组
(?:pattern)的唯一作用是:声明该括号仅用于做正则的分组逻辑(比如优先级控制、量词作用范围限定),不会作为独立的捕获组被存入match对象的groups结果中,它匹配到的内容不会被丢弃,只是不会被单独标记为一个可提取的分组项。
差异来源:两个方法的返回规则完全不同
re.match的返回规则
re.match返回的是整个正则匹配成功后的match对象,调用.groups()或者.group(N)时,只会拿到正则里显式定义的捕获组内容,非捕获组的内容不会出现在分组列表里,和你之前看到的URL示例表现完全一致。
re.findall的返回规则
re.findall的返回结果由正则中是否存在捕获组直接决定:
- 正则中无任何捕获组:返回所有整个正则匹配到的完整子串
- 正则中有1个捕获组:返回所有该捕获组匹配到的内容组成的列表
- 正则中有N个(N≥2)捕获组:返回所有由N个捕获组的匹配结果组成的元组构成的列表
场景验证
你查找DNA连续重复序列时用的正则re.findall("(?:<pattern>)+", <string>)中,整个正则没有定义任何捕获组,所以re.findall会返回整个正则匹配到的完整子串——也就是连续重复的<pattern>拼接后的完整片段,刚好符合你的需求。
我们可以用URL场景验证规则的一致性:
- 正则为
r"(?:https?|ftp)://(stackoverflow.com)"(1个捕获组),re.findall返回结果为["stackoverflow.com"],仅返回捕获组内容,非捕获组的协议部分不会作为单独项返回 - 正则为
r"(https?|ftp)://(stackoverflow.com)"(2个捕获组),re.findall返回结果为[("https", "stackoverflow.com")],返回两个捕获组的匹配结果 - 正则为
r"(?:https?|ftp)://stackoverflow.com"(无捕获组),re.findall返回结果为["https://stackoverflow.com"],返回整个正则的匹配结果,非捕获组的协议部分包含在完整结果中
总结
非捕获组的行为在所有re方法中都是统一的,你感知到的差异只是re.match和re.findall本身的返回逻辑不同导致的。re.findall返回的是非捕获组参与匹配的完整正则结果,并没有违反“非捕获组不被单独捕获”的规则。
内容的提问来源于stack exchange,提问作者spydermayne
相关产品推荐
相关产品推荐

