Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 371|回复: 0

[正则表达式学习]正则表达式匹配的不同情况:贪婪与勉强)

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-28 23:58:43 | 显示全部楼层 |阅读模式
    import java.util.regex.Matcher;
        import java.util.regex.Pattern;
          
        public class Test {
        public static void main(String[] args) {
        String str = "<biao><>c<b>";
        Pattern pattern;
        Matcher matcher;
          
        // 贪婪: 最长匹配 .* : 输出: <biao><>c<b>
        pattern = Pattern.compile("<.*>");
        matcher = pattern.matcher(str);
        while (matcher.find()) {
        System.out.println(matcher.group());
        }
          
        //非贪婪 .*? : 输出: <biao>, <>, <b>
        pattern = Pattern.compile("<.*?>");
        matcher = pattern.matcher(str);
        while (matcher.find()) {
        System.out.println(matcher.group());
        }
          
        // 使用组, 输出<>里的内容, 输出: "biao", " ", "b"
        // 0组代表整个表达式, 子组从1开始
        pattern = Pattern.compile("<(.*?)>");
        matcher = pattern.matcher(str);
        while (matcher.find()) {
        System.out.println(matcher.group(1));
        }  
        }
        }
         在贪婪、勉强和侵占三个量词间有着细微的不同。
         贪婪(*, ?, +):读入整个串,从后往前匹配
         勉强(*?, ??, +?):从前往后匹配
         侵占(*+, ?+, ++):读入整个串,从前往后匹配,匹配的是整个串
    贪婪量词之所以称之为“贪婪的”,这是由于它们强迫匹配器读入(或者称之为吃掉)整个输入的字符串,来优先尝试第一次匹配,如果第一次尝试匹配(对于整个输入的字符串)失败,匹配器会通过回退整个字符串的一个字符再一次进行尝试,不断地进行处理直到找到一个匹配,或者左边没有更多的字符来用于回退了。赖于在表达式中使用的量词,最终它将尝试地靠着 1 或 0 个字符的匹配。

    但是,勉强量词采用相反的途径:从输入字符串的开始处开始,因此每次勉强地吞噬一个字符来寻找匹配,最终它们会尝试整个输入的字符串。

    最后,侵占量词始终是吞掉整个输入的字符串,尝试着一次(仅有一次)匹配。不像贪婪量词那样,侵占量词绝不会回退。
    为了说明一下,看看输入的字符串是 xfooxxxxxxfoo 时。
      
       
    1. Enter your regex: .*foo  // 贪婪量词
    2. Enter input string to search: xfooxxxxxxfoo
    3. I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.
    4. Enter your regex: .*?foo  // 勉强量词
    5. Enter input string to search: xfooxxxxxxfoo
    6. I found the text "xfoo" starting at index 0 and ending at index 4.
    7. I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.
    8. Enter your regex: .*+foo // 侵占量词
    9. Enter input string to search: xfooxxxxxxfoo
    10. No match found.
    复制代码

         第一个例子使用贪婪量词.*[/code],寻找紧跟着字母“f”“o”“o”的“任何东西”零次或者多次。由于量词是贪婪的,表达式的.*[/code]部分第一次“吃掉”整个输入的字符串。在这一点,全部表达式不能成功地进行匹配,这是由于最后三个字母(“f”“o”“o”)已经被消耗掉了。那么匹配器会慢慢地每次回退一个字母,直到返还的“foo”在最右边出现,这时匹配成功并且搜索终止。

    然而,第二个例子采用勉强量词,因此通过首次消耗“什么也没有”作为开始。由于“foo”并没有出现在字符串的开始,它被强迫吞掉第一个字母(“x”),在 0 和 4 处触发了第一个匹配。测试用具会继续处理,直到输入的字符串耗尽为止。在 4 和 13 找到了另外一个匹配。

    第三个例子的量词是侵占,所以在寻找匹配时失败了。在这种情况下,整个输入的字符串被 .*+[/code]消耗了,什么都没有剩下来满足表达式末尾的“foo”。
      
       

       
         
         
          
          

            
          

            
          
         
       

      


    源码下载:http://file.javaxxz.com/2014/10/28/235843437.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-19 09:51 , Processed in 0.411593 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表