java中的正则表达式捕获组与引用的概念
今天群里有个人问,怎样用增则表达式匹配三角形的三边,其实只是要匹配三个数字而已,如 301 402 503 开始认为很简单,我就写了一个 "(([1-9]\\d?)\\s){2}$2" 结果他说错了,我感觉很奇怪,于是自己打开电脑试了试,果然是错的,然后看了看以前的笔记,发现我的Back 引用捕获组错了,因为$符号是在不同字符串中对捕获组的引用看下面这个方法
public static void text_1()
{
String str="我。。我要。。。要要要。。学。。学。编。。。程";
str=str.replaceAll("\\。+","");
System.out.println(str);
<span style="background-color: rgb(255, 255, 153);">str=str.replaceAll("(.)\\1*","$1");</span>
System.out.println(str);
}
这句话的意思是将$1调用(.)匹配到的结果,注意是匹配到的结果,也就是()括号里匹配到什么就被调用什么,这也是本人为什么要写这篇博客的原因所在。
可能大家还没有理解我的意思,下面跟着我来理解
上面说的$是在不同字符串中的引用捕获组,我一直强调的是引用的是结果,看下面这个代码:
public void test()
{
<span style="color:#3333ff;">String regex="(([1-9]\\d?)\\s){2}\2";</span>
String str="3 4 5";
System.out.println(str.matches(regex));
}
上面这段代码是我一直想不懂最后的结果为什么是false,String regex="(([1-9]\\d?)\\s){2}\2";
我们来分析这句话:([1-9]\\d?) 这句的意思是匹配一个正整数,如3,401,等 。([1-9]\\d?)\\s这句话是匹配一个数之后空格隔开,(([1-9]\\d?)\\s){2}正好出现两次也就是如:3 4 ,最后\2是调用角标为2的捕获组,也就是([1-9]\\d?) ,自己一直在思考为什么是错的,知道看到一篇博文才恍然大悟,引用捕获组的不是捕获组里面的表达式,而是引用捕获组所捕获到的具体内容,拿上面的例子来说:当第一次匹配时,([1-9]\\d?)
此匹配组所捕获的是3这个具体的字符串,所以你下次引用时就必须为3这个字符串,而不是再次调用([1-9]\\d?) 这个正则表达式这么简单,这就是我以前最大的误区,所以,自己也是花了很多时间才发现,改正上面的代码:
public static void test()
{
<span style="color:#000099;">String regex="([1-9]\\d*\\s){2}[1-9]\\d*";</span>
String str="304 4 5";
System.out.println(str.matches(regex));
}
归根结底是我将{n}出现次数和\n引用捕获组搞混淆了,希望大家不要记错了!!!下面是我为大家扒过来的我觉得比较好的博文,这里我只是强调捕获组引用的概念,其他关于正则表达式不做过多的介绍,(现在已经深夜1.30了,哎,苦逼的程序员人生啊,该睡了)看下面代码:
Regex :
- 本文主要讲述正则表达式中的捕获组(Capturing Group)的概念
- 本文的正则表达式在 Java 中测试(需要注意的是这里的部分正则表达式在 Java7 中才能应用,下面会注明)
- 本文正则表达式用 高亮标出
Capturing Group : (X)
简单的理解就是把正则表达式中的某部分用 () 括起来表示为一个组,纯理论解释不怎么好解释,详细还看下面的举例。
举例:
- (Ggi)cci 与Ggicci 都匹配 "Ggicci",只不过前面把 Ggi 作为一个捕获组,在匹配到的同时它可以捕获 "Ggi" 这样的字符串供逆向引用(Back
Reference),见下一栏。 - Ggicci* 与(Ggicci)* 不同在于Ggicci* 匹配的是 "Ggicci" 和 "Ggicci…i" 这种情况,而(Ggicci)* 匹配的是
"Ggicci" 和 "GgicciGgicci…Ggicci" 这种情况。
Back Reference :
逆向引用指的是正则表达式中某个捕获组捕获到的字符串供正则表达式构建其自身匹配规则的方式。这是我自己归纳的理论,听起来肯定很晦涩,详细见下面讲解
捕获组的编号与命名:
如 ((A)(B(C))) “摘自Java7 Doc”,这里有 4 个组:
| 编号 | 捕获组 |
| 1 | ((A)(B(C))) |
| 2 | (A) |
| 3 | (B(C)) |
| 4 | (C) |
在未对捕获组人为命名的时候,对捕获组的编号是默认的从左到右依次萃取 ( 和与之对应成一对的 )。如上,一共 4 个 ( ,所以有 4 个组,按 ( 的出现次序编号。
- (?<name>X) 命名捕获组为 name,在 Java7 中;
1: String source = "Ggicci was born in 1991 and is 20 years old now. He weights 54kg and is 170cm tall.";
2: Pattern pattern = Pattern.compile("(?<user>[Gg]gicci)|(?<digital>\\d+)");3: Matcher matcher = pattern.matcher(source);
4: while (matcher.find()) {5: System.out.println(matcher.group());
6: }
代码中的正则表达式(已加粗)匹配 Ggicci 或 ggicci 或一段数字,输出为:1: //输出:
2: Ggicci
3: 1991
4: 20
5: 54
6: 170
(?<user>[Gg]gicci) 把捕获组命名为 user,我们用 Matcher 类的 group(String name) 方法,即 matcher.group("user"); 可以获取该捕获组捕获的内容,其它的捕获组内容将为 null:1: System.out.println(matcher.group("user")); //替换上面 while 循环中的输出语句2: //输出:
3: Ggicci
4: null
5: null
6: null
7: null
当然用 Matcher 类的 group(int group) 方法也可以,这里 user 捕获组的默认编号为 1,所以 matcher.group(1) 同 matcher.group("user") 一样。(?<digital>\d+) 也同样去理解。 - (?:X) 取消捕获组命名,注意这种方式连捕获组默认的编号也会取消,所以在调用 Matcher.group(int) 或 Matcher.group(String) 的时候会异常;
- \n 表示引用第 n 个捕获组捕获到的内容;
1: String source = "Hello, my my name is uh.. is is Gg.. ggicci ggicci ggicci ggicci";
2: Pattern pattern = Pattern.compile("\\b(\\w+)\\b((\\s+)\\1\\b)+");3: Matcher matcher = pattern.matcher(source);
4: while (matcher.find()) {5: System.out.println(matcher.group());
6: }
这段正则表达式 \b(\w)\b((\s+)\1)+ 匹配字符串重复的以空格符间隔的单词。其中 \1 引用了捕获组 (\w) 匹配到的内容。比如
(\w) 第一次匹配了 "Hello",\1 引用了 "Hello" 后正则表达式其实已经变成了\bHello\b((\s+)Hello)+ 了(这是从形式上去理解,具体内部机制如何,亲,我目前真的不知道 : )),但是显然后面没有 "Hello" 可以匹配了,(\w) 第二次匹配了 "my",\1 引用了 "my",找到匹配,然后依次下去,输出如下:1: //输出:
2: my my
3: is is
4: ggicci ggicci ggicci ggicci
- \k<name> 表示引用命名为 name 的捕获组捕获到的内容,在Java7 中;
1: //这里同上面的正则表达式一样,只不过给 \1 取了个名字叫 repeat
2: //然后用 \k<repeat> 代替 \1 而已
3: Pattern pattern = Pattern.compile("\\b(?<repeat>\\w+)\\b((\\s+)\\k<repeat>\\b)+");
java中的正则表达式捕获组与引用的概念的更多相关文章
- 译:Java 中的正则表达式性能概述
原文链接:https://www.baeldung.com/java-regex-performance 作者: baeldung 译者:Darren Luo 1. 概述 在本快速教程中,我们将展示模 ...
- 9.JAVA中的正则表达式
一.JAVA中的正则表达式 1.概念:以某种特定的方式描述字符串 1.Java中正则表达式的规则 ? #{0,1}-?有一个-或者没有 \\ #表示一个" ...
- JAVA中的正则表达式--待续
1.关于“\”,在JAVA中的正则表达式中的不同: 在其他语言中"\\"表示为:我想要在正则表达式中插入一个普通的反斜杠: 在Java中“\\”表示为:我想要插入一个正则表达式反斜 ...
- java中使用正则表达式匹配字符串
在Java中使用正则表达式去匹配相应的字符串: String importFileRole = "(import)\\s*[a-zA-Z0-9_<>.]+\\;";// ...
- (转)Java中使用正则表达式的一个简单例子及常用正则分享
转自:http://www.jb51.net/article/67724.htm 这篇文章主要介绍了Java中使用正则表达式的一个简单例子及常用正则分享,本文用一个验证Email的例子讲解JAVA中如 ...
- Java中带包(创建及引用)的类的编译
Java中带包(创建及引用)的类的编译与调试 java源程序的编译大家都知道,也就是cmd中到源文件所在目录下javac **.java即可,当程序中有包声明还能简简单单的直接javac **.jav ...
- 【java 正则表达式】记录所有在java中使用正则表达式的情况
本篇记录在java中邂逅正则表达式的所有美丽瞬间.因为在java和js中正则表达式的语法并不一致. 1.匹配字符串中有出现[2.1开头或者&2.1或者&3.1等的] Pattern m ...
- Java中到底是值传递还是引用传递?
Java中到底是值传递还是引用传递? 我们先回顾一下基本概念 实参和形参 参数在编程语言中是执行程序需要的数据,这个数据一般保存在变量中.在Java中定义一个方法时,可以定义一些参数, 举个例子: p ...
- [转载]Java中异常的捕获顺序(多个catch)
http://blog.sina.com.cn/s/blog_6b022bc60101cdbv.html [转载]Java中异常的捕获顺序(多个catch) (2012-11-05 09:47:28) ...
随机推荐
- T-SQL流程控制语句
文章目录 if else语句 简单case语句 搜索式case语句 while语句 if else语句 格式: IF 布尔表达式 BEGIN END ELSE BEGIN END 示例: DECLAR ...
- Object.defineProperty(obj,prop,descriptor)使用
初步实现了数据自动映射到html中,动态修改对象数据也很自动更新到html.提供addProps方法-添加新增属性并初始化自动监听代码如下: 1.abserve.js:包含数据监听实现.类似jquer ...
- javaMail的使用以及trying to connect to host "1xxx@163.com", port 25, isSSL false异常
最近项目用到邮件系统,开始了解javaMail...话不多说先上代码: pom依赖: <!-- 邮件 https://mvnrepository.com/artifact/javax.m ...
- UVA 10944 Nuts for nuts..
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=21&p ...
- [原创]networkx 画中文节点
一直想分享一些自己遇到的坑,但确实很多时候走的太快 很多想做的事情会被快节奏的生活冲淡, 在公司做事反而比学校还自在, 因为是悠闲的实习期... 几点小建议写在前头--xdj: 遇到问题,大多数人首先 ...
- py3.0第四天 函数,生成器迭代器等
1.列表生成式,迭代器&生成器 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 > ...
- C++数论板题(弹药科技):Lengendre定理和欧拉函数
弹药科技 时间限制: 1 Sec 内存限制: 128 MB 题目描述 经过精灵族全力抵挡,精灵终于坚持到了联络系统的重建,于是精灵向人类求助, 大魔法师伊扎洛决定弓}用博士的最新科技来抗敌. 伊扎洛: ...
- angular 实现 echarts 拖动区域进行放大 方法
实现逻辑: 1.通过鼠标摁下事件 和弹出事件 获取x轴的index 之后去x轴的list中去获取两个坐标点 2.之后将这两个数据作为参数 传到后台更新数据 3.记录下来这两个坐标点 放到lis ...
- 【Golang】如何统一处理HTTP请求中的异常捕获
最近写GOLANG项目,不使用框架,路由选择httprouter 现在想实现一个需求:在不修改httprouter源码的前提下,对所有注册的路由handle进行异常捕获. 大家都知道golang使用p ...
- Django积木块八——三级联动
三级联动 前端需要的效果,省之后市之后现,创建model,查询所有的省的信息,json传到前面,之后通过省的id找到对应的市,是用异步实现的. # model class Sheng(models.M ...