String s = "fujak superpix172 camera 7.2 megapixel digital camera featuring six shooting modes and 3x optical zoom. silver.";
String reg1 = ".*\\b.camera\\b.*";
String reg1 = ".*\\b..camera\\b.*"; (多了个‘.’号)
结果:
s.matches(reg1) = true;
s.matches(reg2) = false;
哪位高手能帮我解释下为什么结果会第一个为true而第二个为false呢?我在上面的字符串中没有“.camera”啊?

解决方案 »

  1.   


    小数点“.”是可以匹配除换行符“\n”外的任意字符的你想不通这个,那我就很难想像你前面后为什么会用“.*”了reg1中的“.camera”匹配到的是“空格camera”,这时的“camera”是“digital”后面的“camera”
    \b或者更确切的说是\w在Java中的表现很奇怪,现在没时候,如果在晚上睡觉前还没有人来解释的话,我再详细说一下吧
      

  2.   

    谢谢3楼的解释,耐心等待ing。
      

  3.   

    其实三楼都解释得差不多了,你首先要理解 . \b 还有 * 在正则表达式中意思
    首先 .,在正则中代表除行终止符外的任何字符 也就是说你的 .camera = 任何一个字符camera,而 ..camera=任何两个个字符camera
    然后是 \b,这个是代表单词边界,如空格、制表符等
    最后是* ,表示了* 之前的表达式可以重复0次或多次,然后你在对应着看就是了
      

  4.   

    按4楼的意思,我可以这样看待第2个正则吗?
    fujak superpix172 camera 7.2 megapixel digital camera featuring six shooting modes and 3x optical zoom. silver.
    ..camera 我可以匹配到第一个 ‘2 camera’,我把2 camera’看错一个单词,那结果应该是 true (可以匹配)啊,但真实结果是false。
    是不是\b有什么特殊之处呢?
      

  5.   

    首先要知道的一点,就是小数点“.”是可以匹配除了换行符“\n”以外的任意字符的
    那么接下来说一下“\b”的意义,基本上所有的资料里都会说“\b”是单词边界,但是至于“单词”的范围却是少有提及
    通常情况下,正则表达式中所谓的“单词”,就是由“\w”所定义的字符所组成的子串
    所以“\b”就相当于
    (?<=\w)(?=\W)
    或者
    (?<=\W)(?=\w)
    在支持ASCII码的语言中,如JavaScript中,“\w”等价于[a-zA-Z0-9_]
    在支持unicode的语言中,如.NET中,默认情况下,“\w”除可以匹配[a-zA-Z0-9_]外,还可以匹配一些本地字符集,如汉字,全角数字等等
    但是在Java中,“\w”的表现是比较奇怪的,Java是支持unicode的,但Java的正则中的“\w”却是等价于[a-zA-Z0-9_]的
    先来看一下“\w”匹配的例子<script language="javascript"> 
        var str = "abc_123中文_d3=efg汉字%";
        var reg = /\w+/g;
        var arr = str.match(reg);
        if(arr != null)
        {
            for(var i=0;i<arr.length;i++)
            {
                document.write(arr[i] + "<br />");
            }
        }
    </script> 
    //JavaScript中输出
    abc_123
    _d3
    efgstring test = "abc_123中文_d3=efg汉字%";
    MatchCollection mc = Regex.Matches(test, @"\w+");
    foreach (Match m in mc)
    {
        richTextBox2.Text += m.Value + "\n";
    }
    //.NET中输出
    abc_123中文_d3
    efg汉字String test = "abc_123中文_d3=efg汉字%";
    String reg = "\\w+";
    Matcher m = Pattern.compile(reg).matcher(test);
    while(m.find())
    {
        System.out.println(m.group());
    }
    //Java中输出
    abc_123
    _d3
    efg可以看到,Java中的输出和JavaScript中是一致的,都是只支持ASCII字符
    那么是不是可以认为\b的匹配范围也是一致的呢看下如下的例子
    源字符串:abc_123中文_d3=汉字efg
    正则表达式:.\b.<script language="javascript"> 
        var str = "abc_123中文_d3=efg汉字%";
        var reg = /.\b./g;
        var arr = str.match(reg);
        if(arr != null)
        {
            for(var i=0;i<arr.length;i++)
            {
                document.write(arr[i] + "<br />");
            }
        }
    </script> 
    //JavaScript中输出
    3中
    文_
    3=
    g汉
    string test = "abc_123中文_d3=efg汉字%";
    MatchCollection mc = Regex.Matches(test, @".\b.");
    foreach (Match m in mc)
    {
        richTextBox2.Text += m.Value + "\n";
    }
    //.NET中输出
    3=
    字%String test = "abc_123中文_d3=efg汉字%";
    String reg = ".\\b.";
    Matcher m = Pattern.compile(reg).matcher(test);
    while(m.find())
    {
        System.out.println(m.group());
    }
    //Java中输出
    3=
    字%可以看到,Java的输出和.NET是一致的,“\b”在Java中是支持unicode的
    所以总的来说,Java中的“\w”是很奇怪的,在使用时需要注意---------------------------------
    小数点“.”和“\b”的意义和匹配范围都清楚以后,再来看下楼主的正则吧
    String s = "fujak superpix172 camera 7.2 megapixel digital camera featuring six shooting modes and 3x optical zoom. silver."; 
    String reg1 = ".*\\b.camera\\b.*"; 
    a) 首先由“.*”取得控制权开始从位置0匹配,由于小数点可以匹配除换行符“\n”外的任意字符,所以它可以从头匹配到尾
    b) 然后控制权交给“\b”,由“\b”匹配结束的位置,左侧为“.”,右侧为空,不满足要求,“.*”进行回溯,让出一个字符“.”,控制权再交给“\b”,由“\b”匹配“r.”中间的位置,匹配成功
    c) 控制权交给“.”,匹配字符串结尾处的“.”,匹配成功
    d) 控制权交给“c”,由“c”在结束位置进行匹配,匹配失败,“.*”再进行回溯,再让出一个字符“e”,重复以上过程b) c) d)
    e) 直到“.*”让出后一个的“ camera”,也就是“.*”只匹配到“ camera”空格前的“digital”,此时控制权交给“\b”,由“\b”匹配“l”和空格间的位置,匹配成功
    f) 控制权交给“.”由“.”匹配空格,匹配成功
    g) 控制权交给“c”,由“c”来匹配“camera”中的“c”,以此类推,由“camera”匹配“camera”
    h) 控制权交给“\b”,由“\b”匹配“a”和空格间的位置,匹配成功
    i) 然后由后面的“.*”来匹配剩余的字符,匹配成功
    此时报告整个表达式匹配成功,匹配的结果为整个源字符串,“\b.camera\b”匹配到的内容是“digital”后面的空格和“camera”String reg1 = ".*\\b..camera\\b.*"; 
    之所以匹配失败,是因为源字符串中只有两处出现了“camera”,而无论哪一个向前两个字符所在的位置,即“72”中间位置和“al”中间位置,都不符合“\b”的要求,所以后面的“\b”没有可以匹配成功的位置,导致整个表达式匹配失败