Java正则表达式命名分组匹配数字结果不符合预期的问题求助
问题分析与解决方案
嘿,这个问题的根源在于正则表达式里非贪婪量词和贪婪量词的相互作用,让我给你拆解下:
你的正则表达式中,(?<PatternThree>\\d+?)用了非贪婪的+?,而它后面跟着的是贪婪的.*。因为Matcher.matches()要求整个字符串都被匹配,贪婪的.*会尽可能多地“吃掉”字符——当非贪婪的\d+?遇到它时,只会匹配最少的满足条件的字符(也就是1个数字),剩下的数字5就被后面的.*给匹配走了,所以你拿到的分组结果是1而不是15。
几个可行的解决方案:
1. 把非贪婪的\d+?改成贪婪的\d+
既然我们需要匹配所有连续的数字,直接用贪婪的+就可以,它会尽可能匹配最多的数字,直到遇到无法匹配的字符(这里后面没有数字了,所以会匹配15)。修改后的正则:
private static final Pattern STANDARD_NAME_PATTERN = Pattern.compile("MySampleString.*?/(?<PatternOne>.+?)/(?<PatternTwo>\\w+?)/PatternThree(?<PatternThree>\\d+).*");
2. 锚定正则到字符串末尾(去掉多余的.*)
因为Matcher.matches()本身就是匹配整个字符串,所以正则最后的.*其实是多余的,反而会干扰匹配。我们可以把正则末尾的.*去掉,或者加上$来明确匹配到字符串结尾,这样\d+?也能匹配到所有数字(因为后面没有.*来抢字符了):
// 方案2a:去掉末尾的.* private static final Pattern STANDARD_NAME_PATTERN = Pattern.compile("MySampleString.*?/(?<PatternOne>.+?)/(?<PatternTwo>\\w+?)/PatternThree(?<PatternThree>\\d+?)"); // 方案2b:用$锚定结尾 private static final Pattern STANDARD_NAME_PATTERN = Pattern.compile("MySampleString.*?/(?<PatternOne>.+?)/(?<PatternTwo>\\w+?)/PatternThree(?<PatternThree>\\d+?)$");
3. 更严谨的匹配(避免.*?的过度匹配)
另外,你开头的MySampleString.*?/其实可以更严谨一点,比如用[^/]+代替.+?来匹配分组内容,这样可以避免跨/的意外匹配(不过这不是你当前问题的直接原因,只是优化建议):
private static final Pattern STANDARD_NAME_PATTERN = Pattern.compile("MySampleString/(?<PatternOne>[^/]+)/(?<PatternTwo>\\w+)/PatternThree(?<PatternThree>\\d+)$");
为什么你的临时方案不好?
你用\\d\\d\\d?固定了数字位数(1-3位),如果后续出现4位数字的情况,就会匹配失败,完全没有扩展性,所以确实不建议采用——上面提到的方案更灵活通用。
内容的提问来源于stack exchange,提问作者Joseph Cox
相关产品推荐
相关产品推荐

