正则表达式 ?:,?=,?!

2015-08-01 Lim Geng 更多博文 » 博客 » GitHub »

正则表达式 regex javascript

原文链接 http://gengliming.com/2015/08/01/regex-some-important-concept/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


分组 非捕获分组

在正则表达式中遇到小括号就可以认为是一个分组,比如/(a)bcda\1/,(a)就是一个分组,\1代表第一个分组。这种分组可以成为 捕获分组。

var reg = /(a)bcd\1/
console.log(reg.test('abcdef')) // false
console.log(reg.test('abcdaef')) // true

\1是个占位符,意思是这里的内容匹配的和第一个分组的一样,比如/(xyz)bcd\1/实际上就等同于/(xyz)bcdxyz/, 与其相对的就是非捕获分组,比如/(?:a)bcda/,(?:a)就是非捕获分组,不能通过\1引用

var reg = /(?:a)bcd\1/
console.log(reg.test('abcdaef')) // false

贪婪 非贪婪

贪婪的意思是尽可能多的匹配,比如:

var str = 'aaaaaabc'
console.log(/a+/.exec(str)) // 'aaaaaa'
console.log(/a+?/.exec(str)) // 'a'

非贪婪的意思就是尽可能少的匹配,如上,其语法的表示就是在+或*后满加一个?。

零宽度断言

零宽度断言就是子表达式只是预测而不匹配,不会改变lastIndex,如下的reg2中的(?=xxxx)就是零宽度断言。

var str = 'abcdef'
var reg1 = /ab(?:cdef)/g
reg1.exec(str)
console.log(reg1.lastIndex) // 6

var reg2 = /ab(?=cdef)/g
reg2.exec(str)
console.log(reg2.lastIndex) // 2

前瞻 后顾

前瞻(lookahead)和后顾(lookbehind),总起来叫lookaround,它们就是零宽度断言,就像匹配行首和行尾,匹配单词边界,不同之处是,lookaround实际上是匹配字符的,但是最终会放弃匹配,只返回是否匹配。这就是为什么它们只叫做断言。它们并不消耗字符,只断言一个匹配是否可能。

前瞻包括:x(?=y) 和 x(?!y) 后顾包括:(?<x)y 和 (?<!)y

?: ?= ?!

(?:x)

匹配'x'但是不记住这个匹配。这里是括号是不捕获的,并且可以让你定义用于正则表达式操作符使用的子表达式。比如/(?:foo){1,2}/,如果表达式是/foo{1,2}/,那{1,2}将只会应用于在'foo'中的最后字符'o'。而使用非捕获括号,{1,2}就会应用于整个'foo'.

x(?=y)

只有'x'的后面是'y'时,才会匹配'x',这叫做(前瞻)lookahead。比如,/Jack(?=Sprat)/,只有'Jack'的后面是'Sprat'时,才会匹配'Jack'。但是'Sprat'并不包含在匹配结果中。

x(?!y)

只有'x'的后面不是'y'时,才会匹配'x',这个叫做否定前瞻(negated lookahead)。比如,/\d+(?!.)/,匹配一个后面不是点的数字。/\d+(?!.)/.exec('3.141')匹配'141',而不是'3.141'。

参考

1.使用正则表达式找出不包含特定字符串的条目 2.Regular Expressions 3.Zero-Length Assertions