分类: java2015-01-16 00:28 1280人阅读 评论(9) 收藏 举报
 

目录(?)[+]

 

上一篇文章《编程思想之正则表达式 》中讲了正则表达式的原理、使用方法和常见的正则表达式总结,本文将进一步探讨Java正则表达中Greedy、Reluctant、Possessive三种策略的区别。

从Java的官方文档http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html中我们可以看到,正则表达式表示数量词的符号有三套,分别是Greedy(贪婪的)、Reluctant(勉强的)和Possessive(独占的)。其含意如下:

Greedy 数量词

X?

X,一次或一次也没有

X*

X,零次或多次

X+

X,一次或多次

X{n}

X,恰好 n 次

X{n,}

X,至少 n 次

X{n,m}

X,至少 n 次,但是不超过 m 次

Reluctant 数量词

X??

X,一次或一次也没有

X*?

X,零次或多次

X+?

X,一次或多次

X{n}?

X,恰好 n 次

X{n,}?

X,至少 n 次

X{n,m}?

X,至少 n 次,但是不超过 m 次

Possessive 数量词

X?+

X,一次或一次也没有

X*+

X,零次或多次

X++

X,一次或多次

X{n}+

X,恰好 n 次

X{n,}+

X,至少 n 次

X{n,m}+

X,至少 n 次,但是不超过 m 次

Greedy、Reluctant、Possessive的区别

实例说话

看上面的表格我们发现这三种数量词的含意都相同(如X?、X??、X?+都表示一次或一次也没有),但他们之间还是有一些细微的区别的。我们先来看一个例子:

1.Greedy

  1. public static void testGreedy() {
  2. Pattern p = Pattern.compile(".*foo");
  3. String strText = "xfooxxxxxxfoo";
  4. Matcher m = p.matcher(strText);
  5. while (m.find()) {
  6. System.out.println("matched form " + m.start() + " to " + m.end());
  7. }
  8. }

结果:

matched form 0 to 13

2.Reluctant

  1. public static void testReluctant() {
  2. Pattern p = Pattern.compile(".*?foo");
  3. String strText = "xfooxxxxxxfoo";
  4. Matcher m = p.matcher(strText);
  5. while (m.find()) {
  6. System.out.println("matched form " + m.start() + " to " + m.end());
  7. }
  8. }

结果:

matched form 0 to 4

matched form 4 to 13

3.Possessive

  1. public static void testPossessive() {
  2. Pattern p = Pattern.compile(".*+foo");
  3. String strText = "xfooxxxxxxfoo";
  4. Matcher m = p.matcher(strText);
  5. while (m.find()) {
  6. System.out.println("matched form " + m.start() + " to " + m.end());
  7. }
  8. }

结果:

//未匹配成功

原理讲解

Greedy数量词被称为“贪婪的”是因为匹配器被强制要求第一次尝试匹配时读入整个输入串,如果第一次尝试匹配失败,则从后往前逐个字符地回退并尝试再次匹配,直到匹配成功或没有字符可回退。

模式串:.*foo

查找串:xfooxxxxxxfoo

结果:matched form 0 to 13

其比较过程如下

Reluctant采用与Greedy相反的方法,它从输入串的首(字符)位置开始,在一次尝试匹配查找中只勉强地读一个字符,直到尝试完整个字符串。

模式串:.*foo

查找串:xfooxxxxxxfoo

结果:matched form 0 to 4

matched form 4 to 13

其比较过程如下

Possessive数量词总是读入整个输入串,尝试一次(仅且一次)匹配成功,不像Greedy,Possessive从不回退,即便这样做也可能使整体匹配成功。

模式串:.*foo

查找串:xfooxxxxxxfoo

结果:

//未匹配成功

其比较过程如下

参考文章:http://docs.oracle.com/javase/tutorial/essential/regex/quant.html

再来看看几个例子:

模式串:.+[0-9]

查找串:abcd5aabb6

结果:matched form 0 to 10

模式串:.+?[0-9]

查找串:abcd5aabb6

结果:matched form 0 to 4

模式串:.{1,9}+[0-9]

查找串:abcd5aabb6

结果:matched form 0 to 10

模式串:.{1,10}+[0-9]

查找串:abcd5aabb6

结果:匹配失败

如果您有什么疑惑和想法,请在评论处给予反馈,您的反馈就是最好的测评师!由于本人技术和能力有限,如果本博文有错误或不足之处,敬请谅解并给出您宝贵的建议!

========================欢迎关注编程思想系列文章========================

编程思想之正则表达式

编程思想之迭代器

编程思想之递归

编程思想之回调

Java正则表达中Greedy Reluctant Possessive 的区别的更多相关文章

  1. 浅谈Java和JavaScript中变量和数据类型的区别

    对于一门编程语言的学习,如果第一步是安装环境,那么第二步一定是学习这门语言的基本规则,变量和数据类型则首当其冲 JavaScipt作为一个蹭Java热度而命名的语言,在很多方面和Java也有一定的相似 ...

  2. java.util包中 Set 和 List 的区别

    http://ligaosong.iteye.com/blog/903692 对于Set 和 List都是 接口 Collection 的子接口 1.Set 不允许重复,List允许重复 2.Set ...

  3. java集合框架中Set和List的区别

    1. Set 接口实例存储的是无序的,不重复的数据.List 接口实例存储的是有序的,可以重复的元素. 2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有Ha ...

  4. java.io.PrintWriter 中 write() 与 print() 的区别

    最终都是重写了抽象类Writer里面的write方法print方法可以将各种类型的数据转换成字符串的形式输出.重载的write方法只能输出字符.字符数组.字符串等与字符相关的数据.

  5. java实际项目中interface和abstract interface 区别

    参考:https://zhidao.baidu.com/question/424485344260391052.html 这2种有什么区别,根据实际项目经验 帮我解答下 谢谢啊~~~~~~~~~问题补 ...

  6. JS写法 数值与字符串的相互转换 取字符中的一部分显示 正则表达规则

    http://www.imooc.com/article/15885 正则表达规则 <script type="text/javascript"> </scrip ...

  7. Java正则中为什么反斜线"\"需要用“\\\\”表示,原因详解。

    首先,我们需要知道在java字符串和正则表达式中,“\”都具有特殊的含义. 一.在Java的字符串中"\"有两个功能 (一)代表特殊字符:\t代表制表符,\n代表换行....等. ...

  8. php 正则表达示中的原子

    原子 原子是正则表达示里面的最小单位,原子说白了就是需要匹配的内容.一个成立的正则表达示当中必须最少要有一个原子.大理石平台精度等级 所有可见不可见的字符就是原子 说明:我们见到的空格.回车.换行.0 ...

  9. url 中非法字符替换,java 正则替换

    url在传输时不允许的一些字符串,参考自:http://www.ietf.org/rfc/rfc1738.txt 以下字符用java正则替换为"_",一句话搞定: "{& ...

随机推荐

  1. CodeIgniter框架——源码分析之Config.php

    CI框架的配置信息被存储在$config数组中,我们可以添加自己的配置信息或配置文件到$config中: $this->config->load('filename'); //加载配置文件 ...

  2. jetty;tomcat;热部署

    [说明]今天上午进行了jetty的插件部署,下午进行了tomcat的插件部署,晚上有其它事情需要回校 一:今日完成 1)搞定插件直接部署到jetty 2)搞定插件直接部署到tomcat 3)了解了一下 ...

  3. 【BZOJ3122】[Sdoi2013]随机数生成器 BSGS+exgcd+特判

    [BZOJ3122][Sdoi2013]随机数生成器 Description Input 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数.   接下来T行,每行有五个整数p,a,b, ...

  4. SharePoint服务器端对象模型 之 访问文件和文件夹(Part 2)

    4.添加文件夹 文件夹的创建方法在文档库和普通列表中稍有不同. 在文档库中,与一般的集合操作相同,直接使用SPFolderCollection的Add(string name)方法即可添加文件夹,例如 ...

  5. python中静态方法、类方法、属性方法区别

    在python中,静态方法.类方法.属性方法,刚接触对于它们之间的区别确实让人疑惑. 类方法(@classmethod) 是一个函数修饰符,表是该函数是一个类方法 类方法第一个参数是cls,而实例方法 ...

  6. Grafana----Table Panel

    新的表面板非常灵活,既支持时间序列的多模式,也支持表.注释和原始JSON数据.它还提供日期格式化和值格式化和着色选项.要查看表板动作和测试不同的配置数据,查看台面板展示在grafana操场. Opti ...

  7. 高并发服务器建议调小 TCP 协议的 time_wait 超时时间

    说明:操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接,在高并发访问下,服 务器端会因为处于 time_wait 的连接数太多,可能无法建立新的连接,所以需要在服务器上 调小此 ...

  8. Python3.6全栈开发实例[008]

    8.有如下变量(tu是个元祖),请实现要求的功能:tu = ("alex", [11, 22, {"k1": 'v1', "k2": [&q ...

  9. return和yield的区别

    # return 返回给调用者值,并结束此函数.#yiled 返回给调用者值,并将指针停留着当前位置.

  10. sql server扫盲系列

    本系列为入门级,不会介绍过于深入的知识.为防止不道德转载(特别是红黑联盟,把我原文地址删掉,其他照搬,无节操无道德),尽可能打上水印和加上原文地址,读者看的不爽请见谅.原文地址:http://blog ...