分类: 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. linux之shell常用命令介绍

    一.cd    切换目录 cd /etc  切换到/etc目录下              cd ~       切换到主目录下 cd  ..      返回上级目录                  ...

  2. [HAOI2012] 容易题[母函数]

    794. [HAOI2012] 容易题 ★★☆   输入文件:easy.in   输出文件:easy.out   简单对比时间限制:1 s   内存限制:128 MB 秒 输入:easy.in 输出: ...

  3. codevs1068 乌龟棋==洛谷P1541 乌龟棋

    P1541 乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家 ...

  4. 《从零开始学Swift》学习笔记(Day 22)——闭包那些事儿!

    原创文章,欢迎转载.转载请注明:关东升的博客    我给Swift 中的闭包一个定义:闭包是自包含的匿名函数代码块,可以作为表达式.函数参数和函数返回值,闭包表达式的运算结果是一种函数类型. Swif ...

  5. 不恰当使用线程池处理 MQ 消息引起的故障

    现状 业务部门反应网站访问特别慢,负责运维监控的同事说MQ消息队列积压了,中间件的说应用服务器内存占用很高,GC 一直回收不了内存,GC 线程占了近 100% 的 CPU,其他的基本上都在等待,数据库 ...

  6. CAS单点登录------未认证授权服务

    问题背景:之前我使用的127.0.0.1进行CAS 直接url 进行过滤! 后来我用nginx 进行反向代理 出现问题:  如下图 第一眼,就在内心想,草这什么鬼! 麻蛋!     ON! 调试了五分 ...

  7. element-ui中下拉菜单中的@click事件不会触发的问题

    只需要将@click=“fun()”改为@click.native=“fun()”,即可监听下拉菜单的点击事件. 如图所示: 嗯,就酱~

  8. 读取用户家目录下的配置文件到properties

    String conf = System.getProperty("user.home") + File.separator + "a.properties"; ...

  9. 常用模块一(os模块、序列化模块(json和pickle))

    一.os模块 os模块是与操作系统交互的一个接口. import os # 和文件和文件夹的操作有关 os.makedirs('dirname1/dirname2') # 可生成多层递归目录 os.r ...

  10. 4.6 基于STM32+MC20地图显示路径功能

    需要准备的硬件 MC20开发板 1个 https://item.taobao.com/item.htm?id=562661881042 GSM/GPRS天线 1根 https://item.taoba ...