鱼C论坛

 找回密码
 立即注册
查看: 6100|回复: 4

[技术交流] 【Java正则表达式】03. 分支结构、捕获组、非捕获组与反向引用

[复制链接]
发表于 2017-2-17 21:24:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 零度非安全 于 2017-2-17 21:22 编辑

前 3 讲 我们简单地共同探讨了 Java 正则表达式,包括简单介绍、标准字符集合、自定义字符集合、量词、贪婪与非贪婪模

式,字符边界匹配问题。接下来这一讲我们继续探索 Java 的正则表达式 —— 分支结构、捕获组与非捕获组以及反向引用

在学习之前,我们首先来看下以下几个表达式及其作用

表达式
作用
| 分支结构
左右两边表达式之间“或”关系,匹配左边或者右边
( ) 捕获组
1. 在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰     
2. 取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到  
3. 每一对括号会分配一个编号,使用 ( ) 的捕获根据左括号的顺序从 1
开始自动编号。捕获元素编号为 0 的第一个捕获是由整个正则表
达式模式匹配的文本                                                                  
(?:Expression)
非捕获组
一些表达式中,不得不使用 ( ),但又不需要保存 ( ) 中子表达式匹配内容,这时可以用非捕获组来抵消
使用 ( ) 带来的副作用                                                                                                                           

下面我来为大家一一举例说明,首先是分支结构,它用符号“ | ”来表示,表示“或”的关系,匹配左边或者右边,如下

0.jpg
我想这个鱼油们都能掌握,因为这个是最简单的 ^_^!!!

第二个以及第三个稍微复杂点,不过别怕,我都会列举很详细的例子来说明其表达的含义

捕获组与非捕获组它们两个都用了一对小括号“ ( ) ”,表示的意思呢 ~ 是分组,那好,对于第一小点:在被修饰匹配次数

的时候,括号中的表达式可以作为整体被修饰,简单点,就是你把括起来的部分当成一个整体,比如我在 01 讲量词时提到

过这样一个表达式“\d\d{6}”,当时还向你们提问为什么匹配的是 7 次而不是 12 次,假如非得匹配 12 次,那么你该怎么

做?我猜你是聪明的,你会把“\d\d”这个表达式用括号括起来当作一个整体看待,那么就可以连续匹配 12 个字符,这个
就印证了捕获组里的第一点。第二点、第三点和非捕获组以及反向引用合在一起讲

在这里我先说下什么是反向引用

反向引用(\nnn)

每一对“ ( ) ”会分配一个编号,使用“ ( ) ”的捕获根据左括号的顺序从 1 开始自动编号。通过反向引用,可以对分组已

捕获的字符串进行引用。

下面我给大家看两张图,如下

1.jpg

2.jpg

上面两张图中的正则表达式唯一不同的就是第二个表达式中末尾多了“ \1 ”,这个是什么意思呢?其实,在你用括号把表

达式“ [a-z]{5} ”括起来时,它就成了一个捕获组,它会把匹配的字符存放到内存当中去,在这之后我们可以再去引用它们

,当你输完正则表达式“ [a-z]{5} ”时,它心领意会地将其匹配出来了(匹配连续 5 个字符),假如在这些匹配出来的字

符串中我只要“ fishafisha ”,“ fishbfishb ”,“fishcfishc”呢?我猜肯定有的鱼油会把重复 5 次改成重复 10 次,即

“ [a-z]{10} ”,可是事实呢?

3.jpg

这并不是我们所要的结果,那该怎么办?这时 反向引用 就起到了作用了,那就是在其末尾添上“ \1 ”,结果就出现如上

面两张图中的第二张图效果,这里的“ \1 ”的意思是将前面捕获到的字符再次重复一次,比如我捕获到了字符串“fisha”

那么我们只需要对其再次重复一次就可以了,数字“ 1 ”代表它的编号。

不过这样会带来一个问题,什么问题呢?就是当你捕获到的字符非常多,非常大的时候,上面我也提到过,它会放入内存当

中,假如你不想把它放入内存当中,那么非捕获组就该上场了,那么我们可以这样来写正则表达式,即“ (?:[a-z]{5}) ”,

其实它的效果和表达式“ ([a-z]{5}) ”所表达的效果一样,不同区别在于一个不在内存中,另一个在内存中,看到这里,估

计有的鱼油会问怎么才能体现它们的不同?一个“ \1 ”就能体现它们的不同之处,我们还是来测试一下,如下

4.jpg

5.jpg

上面第二张图末尾加了“ \1 ”却没有匹配结果出来,这是为什么呢?我想聪明的你应该知道答案了

提醒:在匹配一些大的文本的时候,非捕获组就显得额外重要了

下一节将介绍正则表达式中的预搜索、零宽断言

【Java正则表达式】04. 预搜索、零宽断言 你可能点了一个假链接。



本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-10-2 12:14:35 | 显示全部楼层
(?:[a-z]{5})\1不在内存中所以引用不到?
但是开头的非捕获组却也没有效果了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-2 14:36:13 | 显示全部楼层
感谢楼主的教程
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-2 15:14:30 | 显示全部楼层
我总感觉正则表达式很难,原因是不清楚所有的正则表达式的最基本的符号所包含通配的符号有哪些,求分享怎么记忆这些符号,并且怎么用来完成无法完成的匹配骚操作
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-28 10:48:19 | 显示全部楼层
黑白色的枫 发表于 2017-10-2 12:14
(?:[a-z]{5})\1不在内存中所以引用不到?
但是开头的非捕获组却也没有效果了

我也疑问这个,这个\1相当于就没用了了,或者说,字符串只是满足了(?:[a-z]{5})(?:[a-z]{5}),但是不捕获
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 02:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表