PCRE2正则引擎如何捕获命名组的所有多次匹配结果?
PCRE2捕获重复命名组的解决方案
PCRE2(包括Perl)不支持自动捕获命名组的所有匹配结果数组,这和.NET正则引擎的行为本质不同——在PCRE2中,重复出现的捕获组(不管命名还是匿名)都会被最后一次匹配覆盖,仅保留最终结果。
针对你的需求,有两种可行的解决思路:
1. 拆分匹配逻辑,分两步处理
先匹配外层结构获取整体内容,再对目标片段单独提取所有子组匹配:
- 第一步:用正则匹配外层结构,捕获
topgroup、maingroup和endgroup:(?<topgroup>(?<maingroup>(?:(?:\h?(Ab|Ba)\h?)(?:\d{1,3}(?:\h?[a-rt-z])?|[A-Ra-rT-Zt-z]\h)\h)*)(?<endgroup>FOO|BAR) - 第二步:对捕获到的
maingroup内容,用子正则循环匹配所有subgroup:
比如在PHP中,你可以用(?:Ab|Ba)\h+(?<subgroup>\d{1,3}(?:\h?[a-rt-z])?)preg_match先拿到maingroup,再用preg_match_all提取所有subgroup的值。
2. 利用PCRE2 API手动追踪捕获位置(代码层面处理)
如果是使用C/C++直接调用PCRE2库,可以通过以下方式获取所有重复捕获的结果:
- 调用
pcre2_match后,通过pcre2_get_ovector_count获取捕获组数量 - 循环遍历匹配过程中每个捕获组的起始和结束偏移量,手动记录每次匹配的内容
- 注意这种方式需要你在代码中处理正则的迭代匹配逻辑,针对重复出现的组位置做追踪
针对你给出的复杂示例,最终要获取2、3g、3a这三个值,推荐第一种拆分逻辑的方案,实现起来更简洁,也更容易维护。
补充:Perl和PCRE2的设计逻辑是,捕获组的作用是记录单次匹配中的分组内容,重复量词不会自动生成数组。如果需要多组结果,必须通过多次匹配或者拆分正则的方式实现。
内容的提问来源于stack exchange,提问作者Lizbeth
相关产品推荐
相关产品推荐

