先看几个例子://匹配'a'与'bd'之间的数字,要求'a'前面不是'c'
    Pattern p = Pattern.compile(".*?(?<!c)a(\\d+)bd.*?");
    Matcher m = p.matcher("dxa34bdza43bdca23bm"); 
    while(m.find()){ 
System.out.println(m.start()+"-->"+m.end());
System.out.println(m.group(1));
    }
结果:
0-->7
34
7-->13
43
    
把 Pattern p赋值为
     Pattern p = Pattern.compile(".*(?<!c)a(\\d+)bd.*");
结果:
0-->19
43第一个例子使用reluctant量词,从左到右,一个个前进匹配
第二个例子使用greedy量词,一次性读完,在一个个回退匹配请问:为什么使用reluctant量词可以找出2个结果(想要的,34,43)
而使用greedy量词,只能得到一个结果?
请指教!最好能结合讲一下Pattern Matcher类,这两个类的源代码超过了我的大脑内存,真长啊,5000多行,我看不下去了!

解决方案 »

  1.   

    一个是贪婪匹配:会搜索a34bdza43bd这个字符串
    一个是懒惰匹配:会搜索a34bd、a43bd两个字符串
    参考一下这个
    http://hi.baidu.com/plulu/blog/item/a4cad087c6cc842fc65cc3b8.html
      

  2.   

    有兴趣的话,可以看看这个帖子 34 楼的回复:http://topic.csdn.net/u/20080325/17/fb7a3e8d-029a-4d8e-89ae-77a9d28ec301.htmljava.util.regex 包中的代码是从开源的正则表达式引擎转译过来的,如果学过编译原理的话应该知道 NFA,
    Java 中正则表达式引擎采用的就是 NFA。反正我是没学过编译原理,也不懂“非确定型有穷自动机”是什么。Pattern 这个类中的代码很复杂,如果没有编译原理、语法分析等知识很难看懂
      

  3.   

    相应的API里面有这两个算法的解释
      

  4.   

    贪婪匹配和惰性匹配的匹配过程是不一样的
    *? +? {n}? {n,m}? {n,}?都是惰性匹配量词,它工作的过程是这样的:
    首先从开始指针处开始查找,若不匹配继续读入下一个字符,直至遇到
    一个匹配为止,是一个递增的过程贪婪匹配的过程正好相反,首先它看从开始至结束的整个字符串是否
    符合匹配,如果不符合他去掉一个末尾一个字符直至符合匹配.整个
    过程是递减的,所以才被形象的叫做贪婪匹配。以上的理解出自
    《JavaScript高级程序设计》,java中的应该也差不多.再看你的字符串:dxa34bdza43bdca23bm
    和表达式      : .*(? <!c)a(\\d+)bd.*
    按匹配拆分下
    dxa34bdz a   43    bd  ca23bm
    .*       a   \\d+  bd  .*
    整个串就完全符合匹配所以根本不需要去掉末尾字符了这是我的理解,没有读过实现源码实现,可不对的地方大家指正。
      

  5.   

    那个说法有点问题,运行了下发现js和jdk1.6下是34。
    看来应该是这样拆分即使更合理些,楼主的错误结果误导了我。
    自己的水平也不怎样,有些牵强附会,自嘲下.
    dx a  34    bd  za43bdca23bm
    .* a  \\d+  bd  .* 
      

  6.   


    火龙果,大哥,我看了http://topic.csdn.net/u/20080325/17/fb7a3e8d-029a-4d8e-89ae-77a9d28ec301.html 这个帖子的34楼,也明白了贪婪与懒惰匹配的区别我想问一下,为什么:
    reluctant量词可以找出2个结果(想要的,34,43) 
    而使用greedy量词,只能得到一个结果?
      

  7.   


    我用的是JDK5.0测试的,我在一楼发的结果,刚验证了是对的
    其中“(? <!c)”,应该是"(?<!c)",我也不知道为什么复制上去会多个空格。js的测试结果,我没测出来(还有语法错误,哈哈我比较菜),我先把它贴出来,晚上在鼓捣鼓捣把,现在上班时间,不宜久留。另外麻烦你给纠正一下:
    <script language="javascript">
    function aaa(){
    alert("贪婪匹配dxa34bdza43bdca23bm");
    var reg="/^.*(?<!c)a(\\d+)bd.*$/";
    alert("dxa34bdza43bdca23bm".match(reg));
    alert("懒惰匹配dxa34bdza43bdca23bm");
    alert("dxa34bdza43bdca23bm".match("/^.*?(?<!c)a(\\d+)bd.*?$/"));
    }
    </script>
    <body>
    <input type="button" value="test" onclick="aaa()"/>
    </body>
    我是用firefox测试的,
      

  8.   

    JavaScript 不支持 (?<!) 和 (?<=) 的逆序环视功能
    JavaScript 仅支持 (?!) 和 (?=) 的顺序环视功能
      

  9.   

    我晕死,脑残的 CSDN 把 < 前面放个空格干嘛?
      

  10.   


    火龙果,大哥,我想再请教这个问题: 我想问一下,为什么: 
    reluctant量词可以找出2个结果(想要的,34,43) 
    而使用greedy量词,只能得到一个结果?
      

  11.   


    先谢谢你热心,耐心,恒心的帮助!
    我看有必要把Mastering Regular Expression这本书下载下来,系统看看了
    我看2两遍了,reluctant量词,greedy量词的区别我明白我的问题是:
    reluctant量词找出2个结果(想要的,34,43)
    greedy量词,只找出2个结果(43)
    引用你在那个34楼的文章:
    “6. a===== 不能匹配表达式,继续吃 
    7. a=====b 呵呵,终于能匹配表达式了,匹配结束

    既然匹配结束了,reluctant量词找到的结果也应该是一个啊。为什么结果是2个那?
      

  12.   

    一个从尾巴开始向前匹配,一个从眼前向后匹配。匹配完毕后,剩下的字符会进行再次匹配。所以贪婪匹配会用掉第一个匹配的第一个字符和第二个匹配的最后一个字符,
    比如匹配 ab
    则他会匹配到 abab 而不是我们期望的ab ab
      

  13.   

    哈哈哈,正荣幸,传说中的老紫竹大哥!为什么,
    reluctant量词找出2个结果(想要的,34,43) 
    greedy量词,只找出1个结果(43) 是不是
    “匹配完毕后,greedy匹配就结束了。”
    而“reluctant匹配完毕后,剩下的字符会进行再次匹配。”
      

  14.   


    字符串:dxa34bdza43bdca23bm 用.*?(?<!c)a(\\d+)bd.*?匹配的时候
    因为.*?(?<!c)a是从左往右匹配,先找到第一个a前面不是c的子字符串,
    1)如果后面匹配\\d+bd(1个以上数字和bd,因为.*?为懒惰匹配,所以后面什么都不匹配了,只匹配到1个数字+字符串bd)如果不匹配从原来c结束的地方从新开始下一次的匹配,
    然后再找后面剩余的字符串中第一个a前面不是c的子串,后面的匹配同上1)用.*(?<!c)a(\\d+)bd.*去匹配的时候
    从右向左找,要先找到一个确定的bd前面是若干个数字,再往前是a,再往前是非c的字符,当匹配的时候,显然只有za43bd的时候才会匹配,因为bd后面是.*所以匹配到字符串结束另外 用.*?(?<!c)a(\\d+)bd.*去匹配的时候,.*?是懒惰匹配,先找到xa34bd匹配,然后.*匹配到字符串结束,也会只是有一个结果