正则表达之零宽断言(零宽度正预测先行断言)
2015-12-04 16:38
120 查看
/article/6041345.html
最近为了对html文件进行源码处理,需要进行正则查找并替换。于是借着这个机会把正则系统地学一下,虽然以前也用过正则,但每次都是临时学一下混过关的。在学习的过程中还是遇到不少问题的,特别是零宽断言(这里还要吐槽下,网上到处都是都复制粘贴的内容,遇到个问题查看了不少重复的东西,汗!!!),所以在这里把自己的理解写下来,方便以后查阅!
零宽度正预测先行断言是什么呢,看msdn上的官方解释定义
(?= 子表达式)
(零宽度正预测先行断言。)仅当子表达式在此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 与后跟数字的单词匹配,而不与该数字匹配。
经典的例子:某单词以ing结尾,要获取ing前面的内容
以上是网上到处可见的例子,到这里或许你明白了,原来就是返回了exp表达式前面的内容。
再看下面的的代码
为什么会返回false?
其实msdn官方定义已经说了,只是它说得很官方而已。这里需要我们注意一个关键点:此位置。没错,是位置而不是字符。那么结合官方定义和第一个例子来理解第二个例子:
因为a后面是b,则此时返回了匹配内容a(由第一个例子知道,只返回a不返回exp匹配的内容),此时a(?=b)c中的a(?=b)部分已经解决了,接下来要解决c的匹配问题了,此时匹配c要从字符串abc哪里开始呢,结合官方定义,就知道是从子表达的位置向右开始的,那么就是从b的位置开始,但b又不匹配a(?=b)c剩余部分的c,所以abc就不匹配a(?=b)c了。
那么如果要上面的进行匹配,正则应该如何写呢?
答案是:a(?=b)bc
当然,有人会说直接abc就匹配上了,还要这么折腾吗?当然不用这么折腾,只是为了说明零宽度正预测先行断言到底是怎么一回事?关于其它的零宽断言也是同一原理!
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面讲下我的理解:
(1).零宽度
这表示匹配是一个位置(Loaction)而不是子表达式。
(2).预测先行,回顾后发
(?= 子表达式),预测先行, 返回与子表达式匹配的前面位置,从做左到右匹配。
(?<= 子表达式),回顾后发,返回与子表达式匹配的后边位置,从右到左匹配。
我们可以想象有在模式匹配过程中有一指针标志当前匹配的位置,这样当子表达式匹配时 预测先行 把指针指到子表达式前边,回顾后发则为后边。可以参考上边代码。
最近为了对html文件进行源码处理,需要进行正则查找并替换。于是借着这个机会把正则系统地学一下,虽然以前也用过正则,但每次都是临时学一下混过关的。在学习的过程中还是遇到不少问题的,特别是零宽断言(这里还要吐槽下,网上到处都是都复制粘贴的内容,遇到个问题查看了不少重复的东西,汗!!!),所以在这里把自己的理解写下来,方便以后查阅!
零宽度正预测先行断言是什么呢,看msdn上的官方解释定义
(?= 子表达式)
(零宽度正预测先行断言。)仅当子表达式在此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 与后跟数字的单词匹配,而不与该数字匹配。
经典的例子:某单词以ing结尾,要获取ing前面的内容
var reg = new Regex(@"\w+(?=ing)"); var str = "muing"; Console.WriteLine(reg.Match(str).Value);//返回mu
以上是网上到处可见的例子,到这里或许你明白了,原来就是返回了exp表达式前面的内容。
再看下面的的代码
var reg = new Regex(@"a(?=b)c"); var str = "abc"; Console.WriteLine(reg.IsMatch(str));//返回false
为什么会返回false?
其实msdn官方定义已经说了,只是它说得很官方而已。这里需要我们注意一个关键点:此位置。没错,是位置而不是字符。那么结合官方定义和第一个例子来理解第二个例子:
因为a后面是b,则此时返回了匹配内容a(由第一个例子知道,只返回a不返回exp匹配的内容),此时a(?=b)c中的a(?=b)部分已经解决了,接下来要解决c的匹配问题了,此时匹配c要从字符串abc哪里开始呢,结合官方定义,就知道是从子表达的位置向右开始的,那么就是从b的位置开始,但b又不匹配a(?=b)c剩余部分的c,所以abc就不匹配a(?=b)c了。
那么如果要上面的进行匹配,正则应该如何写呢?
答案是:a(?=b)bc
当然,有人会说直接abc就匹配上了,还要这么折腾吗?当然不用这么折腾,只是为了说明零宽度正预测先行断言到底是怎么一回事?关于其它的零宽断言也是同一原理!
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
(?= 子表达式) | (零宽度正预测先行断言。) 仅当子表达式在此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。 |
(?<= 子表达式) | (零宽度正回顾后发断言。) 仅当子表达式在此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯。 |
http://deerchao.net/tutorials/regex/regex.htm (?<= # 断言要匹配的文本的前缀 <(\w+)> # 查找尖括号括起来的字母或数字(即HTML/XML标签) ) # 前缀结束 .* # 匹配任意文本 (?= # 断言要匹配的文本的后缀 <\/\1> # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签 ) # 后缀结束
下面讲下我的理解:
(1).零宽度
这表示匹配是一个位置(Loaction)而不是子表达式。
(2).预测先行,回顾后发
(?= 子表达式),预测先行, 返回与子表达式匹配的前面位置,从做左到右匹配。
(?<= 子表达式),回顾后发,返回与子表达式匹配的后边位置,从右到左匹配。
我们可以想象有在模式匹配过程中有一指针标志当前匹配的位置,这样当子表达式匹配时 预测先行 把指针指到子表达式前边,回顾后发则为后边。可以参考上边代码。
相关文章推荐
- 12个Unity5中优化VR 应用的技巧
- 一键安装lnmp脚本
- PPI是什么意思 手机屏幕PPI计算公式
- 12个Unity5中优化VR 应用的技巧
- Ubuntu 安装 Redis
- 笔记
- android学习笔记(七):Handler消息传递机制
- linux网络配置和工具
- nsdata和nsstring的转换
- iOS 解析xml
- web.xml的配置及加载顺序
- 使用Let's Encrypt客户端免费申请SSL证书
- 12306之梆梆加固libsecexe.so的脱壳及修复
- Redis常用命令
- ios中实现图片的播放
- mybatis mapper的配置
- 初探物联网 - 基于Arduino的气象站和View and Data API的结合实例
- 试一下SVG
- nvm 设置默认 node 版本
- 企业网站建设 企业网络信息化不可怀疑的力量