贪婪、勉强和侵占量词间的不同
  在贪婪、勉强和侵占三个量词间有着细微的不同。
  贪婪(*, ?, +):读入整个串,从后往前匹配
  勉强(*?, ??, +?):从前往后匹配
  侵占(*+, ?+, ++):读入整个串,从前往后匹配,匹配的是整个串
  贪婪量词之所以称之为“贪婪的”,这是由于它们强迫匹配器读入(或者称之为吃掉)整个输入的字符串,来优先尝试第一次匹配,如果第一次尝试匹配(对于整个输入的字符串)失败,匹配器会通过回退整个字符串的一个字符再一次进行尝试,不断地进行处理直到找到一个匹配,或者左边没有更多的字符来用于回退了。赖于在表达式中使用的量词,最终它将尝试地靠着 1 或 0 个字符的匹配。
  但是,勉强量词采用相反的途径:从输入字符串的开始处开始,因此每次勉强地吞噬一个字符来寻找匹配,最终它们会尝试整个输入的字符串。
  最后,侵占量词始终是吞掉整个输入的字符串,尝试着一次(仅有一次)匹配。不像贪婪量词那样,侵占量词绝不会回退,即使这样做是允许全部的匹配成功。
  为了说明一下,看看输入的字符串是 xfooxxxxxxfoo 时。
Enter your regex: .*foo  // 贪婪量词
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // 勉强量词
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // 侵占量词
Enter input string to search: xfooxxxxxxfoo
No match found.
  第一个例子使用贪婪量词.*,寻找紧跟着字母“f”“o”“o”的“任何东西”零次或者多次。由于量词是贪婪的,表达式的.*部分第一次“吃掉”整个输入的字符串。在这一点,全部表达式不能成功地进行匹配,这是由于最后三个字母(“f”“o”“o”)已经被消耗掉了。那么匹配器会慢慢地每次回退一个字母,直到返还的“foo”在最右边出现,这时匹配成功并且搜索终止。
  然而,第二个例子采用勉强量词,因此通过首次消耗“什么也没有”作为开始。由于“foo”并没有出现在字符串的开始,它被强迫吞掉第一个字母(“x”),在 0 和 4 处触发了第一个匹配。测试用具会继续处理,直到输入的字符串耗尽为止。在 4 和 13 找到了另外一个匹配。
  第三个例子的量词是侵占,所以在寻找匹配时失败了。在这种情况下,整个输入的字符串被.*+消耗了,什么都没有剩下来满足表达式末尾的“foo”。
  你可以在想抓取所有的东西,且决不回退的情况下使用侵占量词,在这种匹配不是立即被发现的情况下,它将会优于等价的贪婪量词。


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 时。
Enter your regex: .*foo  // 贪婪量词
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // 勉强量词
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // 侵占量词
Enter input string to search: xfooxxxxxxfoo
No match found.
  第一个例子使用贪婪量词.*,寻找紧跟着字母“f”“o”“o”的“任何东西”零次或者多次。由于量词是贪婪的,表达式的.*部分第一次“吃掉”整个输入的字符串。在这一点,全部表达式不能成功地进行匹配,这是由于最后三个字母(“f”“o”“o”)已经被消耗掉了。那么匹配器会慢慢地每次回退一个字母,直到返还的“foo”在最右边出现,这时匹配成功并且搜索终止。
  然而,第二个例子采用勉强量词,因此通过首次消耗“什么也没有”作为开始。由于“foo”并没有出现在字符串的开始,它被强迫吞掉第一个字母(“x”),在 0 和 4 处触发了第一个匹配。测试用具会继续处理,直到输入的字符串耗尽为止。在 4 和 13 找到了另外一个匹配。
  第三个例子的量词是侵占,所以在寻找匹配时失败了。在这种情况下,整个输入的字符串被.*+消耗了,什么都没有剩下来满足表达式末尾的“foo”。
  你可以在想抓取所有的东西,且决不回退的情况下使用侵占量词,在这种匹配不是立即被发现的情况下,它将会优于等价的贪婪量词。


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));
}
}
}

java正则(贪婪、勉强)的更多相关文章

  1. java 正则 贪婪匹配 匹配sql语句中的引号内容

    public class Demo { public static void main(String[] args) { String sql1 = "use test;select * f ...

  2. JAVA 正则表达式的三种模式: 贪婪, 勉强和占有的讨论

    假设待处理的字符串是  xfooxxxxxxfoo 模式.*foo (贪婪模式): 模式分为子模式p1(.*)和子模式p2(foo)两个部分. 其中p1中的量词匹配方式使用默认方式(贪婪型). 匹配开 ...

  3. Java正则表达中Greedy Reluctant Possessive 的区别

    Java正则表达中Greedy Reluctant Possessive 的区别 分类: java2015-01-16 00:28 1280人阅读 评论(9) 收藏 举报 正则表达式Java   目录 ...

  4. Java正则速成秘籍(二)之心法篇

    导读 正则表达式是什么?有什么用? 正则表达式(Regular Expression)是一种文本规则,可以用来校验.查找.替换与规则匹配的文本. 又爱又恨的正则 正则表达式是一个强大的文本匹配工具,但 ...

  5. Java正则速成秘籍(一)之招式篇

    导读 正则表达式是什么?有什么用? 正则表达式(Regular Expression)是一种文本规则,可以用来校验.查找.替换与规则匹配的文本. 又爱又恨的正则 正则表达式是一个强大的文本匹配工具,但 ...

  6. Java正则速成秘籍(三)之见招拆招篇

    导读 正则表达式是什么?有什么用? 正则表达式(Regular Expression)是一种文本规则,可以用来校验.查找.替换与规则匹配的文本. 又爱又恨的正则 正则表达式是一个强大的文本匹配工具,但 ...

  7. java 正则匹配空格字符串 正则表达式截取字符串

    java 正则匹配空格字符串 正则表达式截取字符串 需求:从一堆sql中取出某些特定字符串: 比如配置的sql语句为:"company_code = @cc and project_id = ...

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

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

  9. 通用且常用的Java正则匹配工具,用以检查邮箱名、电话号码、用户密码、邮政编码等合法性

    一个通用且常用的Java正则匹配工具,用以检查邮箱名.电话号码.用户密码.邮政编码等合法性. import java.util.regex.Matcher; import java.util.rege ...

随机推荐

  1. 实盘交易哪些代码BUG产生严重亏损

    1.少写一个return,疯狂开平2900次,以爆仓结束 2.在上生产环境前,不小心误删除了一个“!”(我至今也不清楚为什么会误删了,晕),导致平仓逻辑一直不满足,不止损,让我损失惨重! 3.卖单变买 ...

  2. 使用connected-react-router使router与store同步

    connected-react-router是一个绑定react-router到redux的组件,来实现双向绑定router的数据到redux store中,这么做的好处就是让应用更Redux化,可以 ...

  3. python的debug神器PySnooper

    同事给我推荐了这个调试神器,一直没工夫看,今天看了下. 原文链接: 史上最方便的Python Debug工具|腾讯技术说 体验了下,感觉最好的用法:1.优先逐行调试:2.一些复杂状态处理或者偶现的bu ...

  4. 《Java核心技术卷I》观赏指南

    Tomxin7 如果你有想看书的计划,但是还在纠结哪些书值得看,可以简单看看"观赏指南"系列,本文会简单列出书中内容,给还没有买书的朋友提供一个参考. 前言 秋招过去很久了,虽然在 ...

  5. Mysql数据库忘记密码找回方法

    Mysql数据库忘记密码找回 a 停止mysql服务 /etc/init.d/mysql stop b 使用--skip-grant-tables启动mysql,忽略授权登录验证 mysqld_saf ...

  6. 吴裕雄--天生自然 JAVASCRIPT开发学习:RegExp 对象

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  7. h5-其他伪元素

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. python语法基础-并发编程-进程-进程池以及回调函数

    ###############   进程池    ############## """ 进程池的概念 为什么会有进程池? 1,因为每次开启一个进程,都需要创建一个内存空间 ...

  9. Java之同步方法处理继承Thread类的线程安全问题

    /** * 使用同步方法处理继承Thread类的方式中的线程安全问题 * */class Window4 extends Thread { private static int ticket = 10 ...

  10. Java架构师笔记-你必须掌握的 21 个 Java 核心技术!(干货)

    闲来无事,师长一向不(没)喜(有)欢(钱)凑热闹,倒不如趁着这时候复盘复盘.而写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,希望可以给大家一些经验,能让大家更好学习和使用Jav ...