正则表达式之:零宽断言不『消费』
正则表达式之:零宽断言不『消费』想理解零宽断言只需要记住一句口诀:零宽断言只『占位』,不『消费』。 没错,零宽断言就是个去麦当劳写作业的小学生~ 之所以想写这篇博客是因为昨天看了@玉伯也叫射雕 的最新博文:《正则表达式中的向后匹配》。在这篇文章中,他提到了零宽断言的相关知识,但最核心的知识点却没涉及,即:零宽断言的用法类似普通的正则子表达式(也叫做分组),但不『消费』字符串。 何为『消费』呢?先来看一道题:
(题目是有点绕口…主要是因为 JS 支持的正则太弱了,所以为了适应它,只好这样出题。) 答案: 目测是:aaa,lll,AAA,nnn。用 JS 完成的话: var re2 = /(w)1{2}(?=(w)2{2})/g; // 用到了 *零宽度正预测先行断言* console.log(s.match(re2)); // 输出 => [ 'aaa','lll','AAA','nnn' ] 零宽度正预测先行断言这名字比较绕,忽略就好,理解了零宽断言之后,也没人去记住这些名字。 之所以要使用 零宽度正预测先行断言 来完成这题是因为字符串 s 中存在重叠的 3个连续相同字符,如果使用普通分组来做的话,就会不小心『消费』了那些字符而导致对他们的匹配被忽略。 – 不熟悉零宽断言的朋友,可能会使用如下的正则来完成这题: var re1 = /((w)2{2})(w)3{2}/g; 这个正则输出的结果是:[‘aaa’,'AAA’],是不合我们预期的。 我们来看看用 re1 进行匹配时,re1 是如何『消费』我们的字符串 s 的: var s = 'aaalllsss0tAAAnnn999'; var re1 = /((w)2{2})(w)3{2}/g; console.log("s is: " + s); console.log(); var res; while(res=re1.exec(s)) { console.log("match result: " + res[1] + ".","re1 comsumed: " + res[0],"re1.lastindex: " + re1.lastIndex,"remain string: " + s.slice(re1.lastIndex)); } 输出的结果是: s is: aaalllsss0tAAAnnn999 re1 result: aaa. re1 comsumed: aaalll,re1.lastindex: 6,remain string: sss0tAAAnnn999 re1 result: AAA. re1 comsumed: AAAnnn,re1.lastindex: 17,remain string: 999 什么是 lastIndex 呢?在 JS 中,我们可以使用 RegExp#exec 对某个字符串进行多次匹配,为了多次匹配的结果不重复,RegExp 每匹配完一次后,就记录好下一次匹配的起始位置,这个位置就是 RegExp#lastIndex。 从上面输出结果我们可以看到,re1 在匹配到了 'aaa’ 后,它就『消费』了 'aaalll’ 这个字符串,到了索引 6 这个位置。 我们再来看看用 re2 进行匹配时,re2 是如何『消费』字符串的: re2 result: aaa. re2 comsumed: aaa,re2.lastindex: 3,remain string: lllsss0tAAAnnn999 re2 result: lll. re2 comsumed: lll,re2.lastindex: 6,remain string: sss0tAAAnnn999 re2 result: AAA. re2 comsumed: AAA,re2.lastindex: 14,remain string: nnn999 re2 result: nnn. re2 comsumed: nnn,re2.lastindex: 17,242)"> 代码就不贴了,我们直接来看输出。由于零宽断言不『消费』字符串,所以当我们第一次匹配到了 'aaa’ 后,re2 的 lastIndex 是在 3 这个位置,在其后的匹配中,它从 3 开始,又到 6 暂停。 |
- VB.NET 字体大小 Pt和Px的区别
- 【月伴流星】GhostW7_SP1_U_x86_V2013.06_OEM通用纯净、装机
- c# – 关于UNION,INTERSECT和EXCEPT的SqlException
- IOException parsing XML document from class path resour
- actionscript-3 – 如何在纯粹的as3空中使用新的StageText?
- imp,exp和expdp,impdp
- 学习 Flexbox 的 18 个优质资源
- ORACLE和MYSQL的简单区别
- 掌握 Ajax,第 5 部分: 操纵 DOM
- 高性能Server---Reactor模型