Java正则提取分组多次匹配结果,解决分组覆盖丢失问题
解决Java正则重复捕获组丢失内容的问题
问题根源
你遇到的问题是Java正则中重复捕获组仅保留最后一次匹配结果:原正则里的(?:,<np>([\\w]+)\\s)*是重复分组,每次匹配都会覆盖该分组的内容,最终只能拿到最后一个匹配的bop,前面的mip、bip被直接覆盖丢失。
解决方案
要捕获数量未知的<np>元素,不能依赖单个正则的重复分组,需拆分两步处理:
- 先匹配出"such as"前后的核心片段;
- 对"such as"后的片段单独遍历,逐个提取每个
<np>内的内容。
修改后的代码实现
import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Detector { private final String input; private final String mainPattern; private final String lemma; private final Map<Integer, String> groups; public Detector(String input, String mainPattern, String lemma) { this.input = input; this.mainPattern = mainPattern; this.lemma = lemma; this.groups = new HashMap<>(); processInput(); } public void processInput() { // 第一步:匹配"such as"前的主体和后面的所有<np>片段 Pattern mainRegex = Pattern.compile(mainPattern); Matcher mainMatcher = mainRegex.matcher(input); int groupIndex = 1; if (mainMatcher.find()) { // 存入"such as"前的内容 groups.put(groupIndex++, mainMatcher.group(1)); // 提取"such as"后的完整片段 String npSection = mainMatcher.group(2); // 第二步:逐个匹配每个<np>内的文本 Pattern npRegex = Pattern.compile("<np>([\\w]+)"); Matcher npMatcher = npRegex.matcher(npSection); while (npMatcher.find()) { groups.put(groupIndex++, npMatcher.group(1)); } } System.out.println(groups); } public static void main(String[] args) { String input = "<np>semitic languages such as <np>Hebrew ,<np>mip ,<np>bip ,<np>bop or <np>Arabic"; // 主正则简化为匹配前后两部分 String mainPattern = "<np>,?([\\w\\s]+)\\s+such as\\s+(.*)"; Detector suchAs = new Detector(input, mainPattern, "mip"); } }
代码说明
- 主正则调整:将原复杂正则拆分为
<np>,?([\\w\\s]+)\\s+such as\\s+(.*),第一组捕获"such as"前的内容,第二组捕获后续所有包含<np>的片段; - 子正则遍历:用
<np>([\\w]+)作为子正则,通过while (npMatcher.find())循环逐个提取每个<np>内的文本,彻底避免重复分组覆盖的问题; - 结果存储:按顺序将所有捕获内容存入
groups,确保没有遗漏。
运行结果
执行后输出:{1=semitic languages, 2=Hebrew, 3=mip, 4=bip, 5=bop, 6=Arabic},所有<np>元素均被正确捕获。
内容的提问来源于stack exchange,提问作者yuval cohen
相关产品推荐
相关产品推荐

