JS中“较高级”的正则表达式知识点

Javascript的正则表达式虽然很早以前就接触过了,那时候还在做编辑的时候,用AS写了一个文本替换的小程序。

最近逛书店,发现有本21天学通XXX的系列书,一向对这种名字的书没有好感,不过还是很好奇地拿了起来,随便翻了一下,正好看到一些以前没有注意到的地方,回来继续查看犀牛书等书补充了一下。

(XXX)

capturing groups(捕获性分组,犀牛书上叫组合)。

这个最常见的,就是用括号把一部分表达式包起来,方便在后面用+或者*或者{n,m}等来表示数量等,又或者有时候要用到|的情况。


(?:XXX)

non capture group (非捕获性分组,犀牛书上叫只组合)

和捕获性分组的区别就是,这里的括号内的内容不被计算入分组,也就是说是不存入$1,$2这些里面的。


x(?=y)

lookahead (零宽度正预测先行断言、先行断言)

匹配x当且仅当x后面紧跟y。

例如,/Jack(?=Sprat)/ 匹配 'Jack' 当且仅当后面是'Sprat'。 /Jack(?=Sprat|Frost)/ 匹配 'Jack' 当且仅当后面是 'Sprat' 或 'Frost' 。然而,无论 'Sprat' 还是 'Frost' 都不会进入匹配的结果里面,就好像宽度为0一样。

注意:lookhehind(零宽度正回顾后发断言、后行断言)在Javascript中是不支持的!也就是说,如果想要匹配java开头的script,是不能使用/(?<java)script/来匹配的。


x(?!y)

negated lookahead(零宽度负预测先行断言、负向先行断言)

匹配 'x' 当且仅当 'x' 后面不是 'y'.

例如,/d+(?!.)/ 匹配一个数字当且仅当后面跟的不是一个小数点。/d+(?!.)/.exec("3.141") 匹配 '141' 而不是 '3.141'。


n

n为正整数

和第n个分组第一次匹配的字符相匹配。

例如,想要/(['"]).*?1/,可以匹配成对引号的内容。意思就是"abc'是不会被匹配的,只有"abc"或者'abc'可以。后面的1必须和前面第一个捕获的内容一模一样。


先行断言和非捕获分组的区别

前者根本就不进入匹配,当然也不进入捕获的分组了;后者会进入匹配,不过不进入捕获分组。

例如,/boy(?=z)/表示的是后面有z字母的boy,即boyz这样的形式的boy满足条件,如果是boy zh 或者boy and 则不匹配,但是!即使是boyz,在捕获的结果里面,z是完全不会出现的;/boy(?:z)/会捕获到整个boyz,而且结果中也是boyz,只不过z不会出现在分组中,也就是$1 != 'a'


其他的细节

使用new的形式新建正则表达式的话,对于反斜杠(backsplash)稍微麻烦一点。

例如, var r=/\\/ 用new的话,需要写成下面的形式:

var r= new RegExp('\\\\');

为什么呢,因为new的话,第一个参数是一个字符串,而字符串里面也是支持反斜杠转义的!

比如 'lm\no'实际上不是lm反斜杠no,而是lm换行o,要达到目的,需要写成'lm\\no'

回到上面的,/\\/这个表示一个反斜杠字符,其本身是含有两个\的正则表达式,所以当里面的两个反斜杠转换成字符串就是四个反斜杠啦!

PS:正则表达式中/不需要转义,所以字符////的正则表达式来表示,同时/字符不需要转义,用new来新建时候直接写作new RegExp('/')

参考资料:

MDN: Regular Expressions
regular-expressions.info

标签: js, 正则表达式, 零宽断言, 先行断言, javascript

添加新评论