java regex possissive relunctant
Java正则表达中Greedy Reluctant Possessive 的区别
上一篇文章《编程思想之正则表达式 》中讲了正则表达式的原理、使用方法和常见的正则表达式总结,本文将进一步探讨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
- public static void testGreedy() {
- Pattern p = Pattern.compile(".*foo");
- String strText = "xfooxxxxxxfoo";
- Matcher m = p.matcher(strText);
- while (m.find()) {
- System.out.println("matched form " + m.start() + " to " + m.end());
- }
- }
结果:
matched form 0 to 13
2.Reluctant
- public static void testReluctant() {
- Pattern p = Pattern.compile(".*?foo");
- String strText = "xfooxxxxxxfoo";
- Matcher m = p.matcher(strText);
- while (m.find()) {
- System.out.println("matched form " + m.start() + " to " + m.end());
- }
- }
结果:
matched form 0 to 4
matched form 4 to 13
3.Possessive
- public static void testPossessive() {
- Pattern p = Pattern.compile(".*+foo");
- String strText = "xfooxxxxxxfoo";
- Matcher m = p.matcher(strText);
- while (m.find()) {
- System.out.println("matched form " + m.start() + " to " + m.end());
- }
- }
结果:
//未匹配成功
原理讲解
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 regex possissive relunctant的更多相关文章
- java Regex
超全 http://www.rexegg.com/regex-lookarounds.html 这篇文章不错:http://www.cnblogs.com/lzq198754/p/5780340.ht ...
- Java Regex match IP address
Reference: [1] https://www.mkyong.com/regular-expressions/how-to-validate-ip-address-with-regular-ex ...
- 【总结】java regex 正则表达式 提取数字和去除数字,过滤数字,提取价格
@Test public void test33() { String phoneString = "哈哈,13888889999"; // 提取数字 Pattern patter ...
- 【Java.Regex】用正则表达式查找Java源文件中的注释
代码: package regex; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.I ...
- 【Java.Regex】用正则表达式查找Java文件里的字符串
代码: import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; imp ...
- 【Java.Regex】使用正则表达式查找一个Java类中的成员函数
代码: import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; imp ...
- java Regex匹配及解析文本
用一个main程序展示下 public static void main(String[] args){ String text = "SSM<br>LOC<b ...
- java中regex参考
在Sun的Java JDK 1.40版本中,Java自带了支持正则表达式的包,本文就抛砖引玉地介绍了如何使用java.util.regex包. 可粗略估计一下,除了偶尔用Linux的外,其他Linu ...
- [Android Tips] 21. Regex Named Groups in Android
Android SDK 并没有包含 Java 7 新增加的命名捕获组功能,需要使用第三方库 https://github.com/tony19/named-regexp import com.goog ...
随机推荐
- 使用javassist运行时动态重新加载java类及其他替换选择
在不少的情况下,我们需要对生产中的系统进行问题排查,但是又不能重启应用,java应用不同于数据库的存储过程,至少到目前为止,还不能原生的支持随时进行编译替换,从这种角度来说,数据库比java的动态性要 ...
- 第一百一十一节,JavaScript,BOM浏览器对象模型
JavaScript,BOM浏览器对象模型 学习要点: 1.window对象 2.location对象 3.history对象 BOM也叫浏览器对象模型,它提供了很多对象,用于访问浏览器的功能.BOM ...
- 4-jQuery - AJAX post()
说明 POST 一般用于向后台发送数据,但也可用于从服务器获取数据.不过,POST 方法不会缓存数据,并且常用于连同请求一起发送数据. 格式 $.post(URL,data,callback); // ...
- jQuery获取元素的兄弟节点的几种方法
$('#id').siblings() //当前元素所有的兄弟节点 $('#id').prev() //当前元素前一个兄弟节点 $('#id').prevaAll() //当前元素之前所有的兄弟节点 ...
- SSL单向认证和双向认证原理
注:本文为个人学习摘录,原文地址:http://edison0663.iteye.com/blog/996526 为了便于更好的认识和理解 SSL 协议,这里着重介绍 SSL 协议的握手协议.SSL ...
- Entity Framework Code First -- Migrations 迁移
在开始使用迁移(Migrations)之前,我们需要一个 Project 和一个 Code First Model, 对于本文将使用典型的 Blog 和 Post 模型 创建一个新的控制台应用程序 M ...
- 二维离散平稳小波分解swt2
对信号X进行N尺度平稳小波分解 [A,H,V,D]=swt2(X,N,'wname'); clc,clear all,close all; load woman; [cA,cH,cV,cD]=swt2 ...
- nefu 1191 平行宇宙 (bfs)
Description 小k是时空贸易者,他经常在两个平行宇宙之间往来经商,现在他要从S点到达E点,问最少需要多长时间.(已知小k在同一个宇宙中只能向上下左右四个方向移动,每次移动需要1个单位时间,且 ...
- MC- 挂单STOP交易
using System; using System.Drawing; using System.Linq; using PowerLanguage.Function; using ATCenterP ...
- chapter9_4 非抢占式的多线程
协同程序与常规的多线程不同之处:协同程序是非抢占式的. 当一个协同程序运行时,是无法从外部停止它的.只有当协同程序显式地调用yield时,它才会停止. 当不存在抢先时,编程会变得简单很多,无须为同步的 ...