在正则表达式世界中,匹配模式分为贪婪匹配和非贪婪匹配两种形式。默认情况下,量词(如*、+、{})会尽可能多地匹配字符,我们称之为"贪婪匹配"。但在某些场景下,这种"贪婪"行为会导致匹配结果超出预期。
非贪婪匹配的实现只需在量词后添加问号(?)即可,例如:
- *?:重复任意次,但尽可能少
- +?:重复1次或更多次,但尽可能少
- {n,}?:重复n次或更多次,但尽可能少
- {n,m}?:重复n到m次,但尽可能少
经典应用场景出现在HTML/XML标签处理中。观察以下示例:
String text = "<div>内容1</div><div>内容2</div>";
// 贪婪匹配(匹配整个字符串)
Pattern greedy = Pattern.compile("<div>.*</div>");
Matcher m1 = greedy.matcher(text);
while (m1.find()) {
System.out.println("贪婪匹配: " + m1.group());
}
// 非贪婪匹配(匹配单个标签)
Pattern reluctant = Pattern.compile("<div>.*?</div>");
Matcher m2 = reluctant.matcher(text);
while (m2.find()) {
System.out.println("非贪婪匹配: " + m2.group());
}
贪婪模式输出结果为整个字符串"<div>内容1</div><div>内容2</div>",而非贪婪模式会分别输出"<div>内容1</div>"和"<div>内容2</div>"两个独立匹配项。
性能考量方面,非贪婪匹配在某些情况下效率更高,因为它一旦找到最小匹配就会停止,而不需要像贪婪匹配那样回溯大量文本。但在复杂表达式中仍需注意回溯问题,可结合占有符(?+)进一步优化性能。
掌握非贪婪匹配技巧能显著提升文本处理的精确度,是每个Java开发者必备的正则表达式高级技能。

被折叠的 条评论
为什么被折叠?



