import java.util.Arrays; public class Test { public static void main(String args[]) { String t='x123xxxxxx123'; Pattern p=Pattern.compile('.*123'); Matcher m=p.matcher(t); System.out.println('===========贪婪模式================'); while(m.find()){ System.out.println('开始'+m.start()); System.out.println(m.group()); System.out.println('结束'+m.end()); } Pattern p1=Pattern.compile('.*?123'); Matcher m1=p1.matcher(t); System.out.println('===========懒惰模式================'); while(m1.find()){ System.out.println('开始'+m1.start()); System.out.println(m1.group()); System.out.println('结束'+m1.end()); } Pattern p2=Pattern.compile('.*+123'); Matcher m2=p2.matcher(t); System.out.println('===========侵入模式================'); while(m1.find()){ System.out.println('开始'+m2.start()); System.out.println(m2.group()); System.out.println('结束'+m2.end()); } } }
模式的陷阱: 当一个表达式中,有多个非贪婪匹配时,或者多个未知匹配次数的表达式时,这个表达式将可能存在效率上的陷阱。有时候,匹配速度慢得莫名奇妙,甚至开始怀疑正则表达式是否实用。 效率陷阱的产生: “如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。” 具体的匹配过程是这样的:
当一个表达式中有多个非贪婪匹配,以表达式 'd(\w+?)d(\w+?)z' 为例,对于第一个括号中的 '\w+?' 来说,右边的 'd(\w+?)z' 属于它的 '右侧的表达式',对于第二个括号中的 '\w+?' 来说,右边的 'z' 属于它的 '右侧的表达式'。 当 'z' 匹配失败时,第二个 '\w+?' 会 '增加匹配一次',再尝试匹配 'z'。如果第二个 '\w+?' 无论怎样 '增加匹配次数',直至整篇文本结束,'z' 都不能匹配,那么表示 'd(\w+?)z' 匹配失败,也就是说第一个 '\w+?' 的 '右侧' 匹配失败。此时,第一个 '\w+?' 会增加匹配一次,然后再进行 'd(\w+?)z' 的匹配。循环前面所讲的过程,直至第一个 '\w+?' 无论怎么 '增加匹配次数',后边的 'd(\w+?)z' 都不能匹配时,整个表达式才宣告匹配失败。 其实,为了使整个表达式匹配成功,贪婪匹配也会适当的“让出”已经匹配的字符。因此贪婪匹配也有类似的情况。当一个表达式中有较多的未知匹配次数的表达式时,为了让整个表达式匹配成功,各个贪婪或非贪婪的表达式都要进行尝试减少或增加匹配次数,由此容易形成一个大循环的尝试,造成了很长的匹配时间。本文之所以称之为“陷阱”,因为这种效率问题往往不易察觉。 举例:'d(\w+?)d(\w+?)d(\w+?)z' 匹配 'ddddddddddd...' 时,将花费较长一段时间才能判断出匹配失败 。 效率陷阱的避免: 避免效率陷阱的原则是:避免“多重循环”的“尝试匹配”。并不是说非贪婪匹配就是不好的,只是在运用非贪婪匹配的时候,需要注意避免过多“循环尝试”的问题。 情况一:对于只有一个非贪婪或者贪婪匹配的表达式来说,不存在效率陷阱。也就是说,要匹配类似 ' | 内容 | ' 这样的文本,表达式 '([^<><(?! d="">))*(?!> | ' 和 '((?! | ).)*' 和 '.*? | ' 的效率是完全相同的。
|