[正则表达式]-基础语法五 反向引用与断言
来源:互联网 发布:按键精灵压枪源码 编辑:程序博客网 时间:2024/05/16 04:51
本文是关于正则表达式基础语法的最后一篇文章,关于正则表达式比较特殊的特性,譬如:递归等高级特性依据不同开发环境与编程语言而异。所以笔者不在赘述这些特殊化的性质。
最后将介绍记录正则表达式中的另一语法基础:反向引用与断言。
还记得元字符 \ 有一个作用吗?那就是反向引用。是这样描述的:\n如果该\n之前至少有n个匹配分组并被命名,则\n代表的是“反向引用”。否则\n代表的就是转义字符,参考与ASCII码表。
一、反向引用
反向引用:当一个正则表达式被分组之后,每一个组将自动被赋予一个组号,该组号可以代表该组的表达式。其中组号的编制规则为:从左到右、以分组的左括号“(”为标识,第一个分组的组号为1,第二个分组的组号为2,依此类推。
从这句话中,笔者可以看到,如果要引用某一段正则表达式,则必须将该段表达式用“()”双括号括起来,以便使正则表达式引擎将之分组编号待用。例如:^([0-9A-Fa-f])ccc\1{2}$ 可以匹配0ccc00 acccaa AcccAA 但是不能匹配AcccBB 或者AcccBC 。原因在于:反向引用\n所匹配的字符必须和其引用的部分正则表达式所匹配到字符串一致。
类似与编程语言中,前面定义了一个变量并赋值为X,后面再使用该变量时,其值仍为X 。
笔者初次在使用引用时,由于没有注意这个引用的特性,导致出现了一个错误。在前面的博文中,提到过十六进制数0-ABCD的正则表达式:
\b(A|a)(B|b)(C|c)[0-9A-Da-d]|(A|a)(B|b)[0-9A-Ba-b][0-9A-Fa-f]|(a|A)[0-9][0-9A-Fa-f]{2}|[1-9][0-9A-Fa-f]{3}|[1-9A-Fa-f][1-9A-Fa-f]{0,2}|0\b
笔者将自己的错误描述一下,希望诸位能够以此为戒。笔者在写完此正则表达式之后,看到表达式段[0-9A-Fa-f]多次出现。所以懂了歪脑筋,将[0-9A-Fa-f]用括号括起来进行了分组编号,认为将之化简了。
\b(A|a)(B|b)(C|c)([0-9A-Da-d])|(A|a)(B|b)[0-9A-Ba-b]\4|(a|A)[0-9]\4{2}|[1-9]\4{3}|[1-9A-Fa-f][1-9A-Fa-f]{0,2}|0\b
此图为未“化简”正则表达式运行之后的结果图:
此图为“化简”之后的正则表达式运行之后的结果图:
看到了吗?是错哒~为何,笔者试图从运算符优先级的角度进行理解,无奈不能解释的通。但是笔者经过测试实验,得到了一套说法:
在反向引用\n和“或”操作同时使用时,需要注意的是:
1、分组编号依然照旧:从左到右,以左括号为标识依次编号1、2、3……
2、“或”操作将表达式分割开来,导致\n反向引用和分组(experssion)必须位于 | 同一侧。
譬如说:
a(b)(c)|(d)(e)\1 × 不能越界引用,甚至导致逻辑混乱
a(b)(c)|(d)(e)\2 × 不能越界引用,甚至导致逻辑混乱
a(b)(c)|(d)(e)\3 √ 匹配abc或者ded
a(b)(c)|(d)(e)\4 √ 匹配abc或者dee
这部分最后笔者想说的是:(experssion)反向引用是不容易使用的,所以使用的时候一定要慎重。
附:分组形式(?<name>experssion)和反向引用\k<name>的使用道理与(experssion)和\n的使用道理一样。还有一个分组形式(?:experssion)只匹配,但不对其进行编号,所以笔者觉得这是个可有可无的东西,比较愚蠢的还没有发现其巨大的作用。读者如果对此有感想,欢迎留言。谢谢。
二、断言
关于断言,有正预测先行断言和回顾后发断言。笔者一一将其列出来。
(?=experssion) 匹配字符串experssion前面的位置。
(?!experssion) 匹配后面不是experssion的位置。
(?<=experssion) 匹配字符串experssion后面的位置。
(?<!experssion) 匹配前面不是experssion的位置。
(?>experssion) 只匹配字符串experssion一次。(知道现在笔者觉得这个好无厘头啊,只匹配一次需要用这么复 杂的结构吗?)
可能不是很好理解,看几个例子就懂了:
这里的正则表达式abc(?=dddd)中的断言部分相当于“条件”。如同编程语言中的if语句一样,这样解释:如果字符串abc的后面是dddd,则该字符串abc是可以被匹配的。
请注意颜色变化,颜色加深的部分,为匹配出来的。这里正则表达式abc(?!dddd)中的断言部分也是相当与条件。不过是这样解释的:如果字符串abc的后面不是dddd,则该字符串abc是可以被匹配的。
请注意(?!experssion)和(?=experssion)两个断言都是先行断言,也就是说只能放在要匹配的字符串的后面。相对应的,有只能放在要匹配的字符串的前面的断言,叫做后发断言(?<=experssion)和(?<!experssion) 。依然是进行测试:
仍有先行断言与后发断言结合起来,形如:(?<=dddd)abc(?=dddd)这样的双重条件,前后都有要求。再次提醒,断言优先级依然比“或”操作 | 优先级要高,所以断言只影响到位于 | 同侧的字符,读者自行理解。
- [正则表达式]-基础语法五 反向引用与断言
- 正则表达式(四)--- 反向引用、断言
- JavaScript正则表达式(基础、分组、懒惰匹配、反向引用和零宽断言)
- 正则表达式分组的反向引用、断言详解
- 正则表达式反向引用
- 正则表达式:反向引用
- 正则表达式:反向引用
- 正则表达式反向引用
- 正则表达式 反向引用
- js中使用正则表达式(五)特殊字符、匹配模式、捕获组与反向引用介绍
- 正则表达式高级用法---五(反向引用 /1, /2...)
- 正则表达式中的反向引用
- 12.正则表达式:反向引用
- 正则表达式之反向引用
- 正则表达式中的反向引用
- 正则表达式的反向引用
- 正则表达式的反向引用
- javascript 正则表达式 反向引用
- 第9课:Scala类和对象彻底实战和Spark源码鉴赏
- 【英语总结】六月
- 折腾记要——Ubuntu 14.04系统安装Nvidia CUDA7.5并搭建Python Theano深度学习开发环境
- redis 配置文件详解
- unity知识结构,可检查自身,可用来教学。
- [正则表达式]-基础语法五 反向引用与断言
- 负载均衡的那些算法们
- Android开发实现中的“再按一次返回键退出程序”
- HTTP响应
- JavaScript split()方法和join()方法
- java中Executor、ExecutorService、ThreadPoolExecutor介绍
- 【嵌入式开发】树莓派支持硬编码的视频套件
- Android之调用百度API显示地图
- openGL中使用混合数组(glInterLeavedArrays)