贪婪、勉强和侵占量词间的不同
在贪婪、勉强和侵占三个量词间有着细微的不同。
贪婪(*, ?, +):读入整个串,从后往前匹配
勉强(*?, ??, +?):从前往后匹配
侵占(*+, ?+, ++):读入整个串,从前往后匹配,匹配的是整个串
贪婪量词之所以称之为“贪婪的”,这是由于它们强迫匹配器读入(或者称之为吃掉)整个输入的字符串,来优先尝试第一次匹配,如果第一次尝试匹配(对于整个输入的字符串)失败,匹配器会通过回退整个字符串的一个字符再一次进行尝试,不断地进行处理直到找到一个匹配,或者左边没有更多的字符来用于回退了。赖于在表达式中使用的量词,最终它将尝试地靠着 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));
}
}
}
- oracle (6)---SQL 数据关联查询
SQL 数据关联查询 Structure Query Language 从多(n)张表查询对应记录信息,必须有至少n-1个关联条件,否则会出现笛卡尔积的情况.1. 等值连接:没有连接关系的数据不会被查 ...
- EF Core开发模式之Code First
Code First顾名思义,代码为先.首先编写完相关的实体类及DbContext派生类,然后通过映射关系自动在数据库中完成数据库表的创建. 本例中创建一个班级和学生的管理,主要有班级类MyClass ...
- Python快速安装库的靠谱办法
我们如果使用python,并且使用pip安装一些库 会经常遇到pip在线安装速度慢 ! 慢也就算了,安装经常会由于timeout等原因中断 所以有没有什么在线安装库并且速度较快的办法么? 其实是有 ...
- 两个exe共享内存数据
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- Java中Scanner类在nextInt()后无法输入nextLine()的问题
首先,Scanner是一个扫描器,它扫描数据都是去内存中一块缓冲区中进行扫描并读入数据的,而我们在控制台中输入的数据也都是被先存入缓冲区中等待扫描器的扫描读取.这个扫描器在扫描过程中判断停止的依据就是 ...
- ZJNU 2356 - 六学家
“选出来三个六学家,他们的编号是i,j,k,满足i<j<k,且a[k]=a[j]-a[i]” 所以输入第i个数a[i]时,直接让答案加上前i-1个数中能构成差值为a[i]的数量即可 然后让 ...
- Tomcat server.xml常用配置 含有外带文件及默认host
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE server-xml [<!ENTITY ...
- Django框架(十):视图(三) Cookie、Session
1. Cookie Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密).Cookie最早是网景公司的前雇员L ...
- javaweb学习——session和Cookie实现购物车功能
1.创建Book类,实现对图书信息的封装. package cn.it.sessionDemo.example1; import java.io.Serializable; /** * 该类实现对图书 ...
- 吴裕雄--天生自然ShellX学习笔记:Shell 数组
数组中可以存放多个值.Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似). 与大部分编程语言类似,数组元素的下标由0开始. Shell 数组用括号来 ...