正则表达式 .*?_正则表达式先后行断言

4054674c053c0880ab9e78796e0c3543.png

一个 先后行断言(Lookaround Assertion)是正则表达式中的一个构造,明确了当前位置的前后字符序列是什么,但没有其他副作用。亦称为零宽断言(Zero-width Assertion)。

当前 JavaScript 唯一支持的 Lookaround Assertion 是 先行断言(Lookahead Assertion),其匹配当前位置接下来的字符序列,而本章描述的 后行断言 提案匹配的是当前位置前面的字符序列。

先行断言

正则表达式中的先行断言意味着:后续字符序列必须与断言相匹配,但没有其他副作用。即,不捕获任何东西,且匹配到的字符串不包含断言部分。

以如下正则表达式为例:

const RE_AS_BS = /aa(?=bb)/;

它匹配字符串 'aabb',但是匹配到的内容是不包含 'bb' 的:

const match1 = RE_AS_BS.exec('aabb');console.log(match1[0]); // 'aa'

而且,它还不匹配那种没有两个 'b' 的字符串:

const match2 = RE_AS_BS.exec('aab');console.log(match2); // null

一个负向先行断言(Negative Lookahead Assertion)意味着后续字符序列必须与该断言不匹配 。例如:

> const RE_AS_NO_BS = /aa(?!bb)/;> RE_AS_NO_BS.test('aabb')false> RE_AS_NO_BS.test('aab')true> RE_AS_NO_BS.test('aac')true

后行断言

后行断言与先行断言的工作方式类似,但是方向相反。

正向后行断言

对于一个正向后行断言(Positive Lookbehind Assertion)来说,当前位置的前继字符序列必须与该断言匹配(没有其他副作用)。

const RE_DOLLAR_PREFIX = /(?<=$)foo/g;'$foo %foo foo'.replace(RE_DOLLAR_PREFIX, 'bar'); // '$bar %foo foo'

正如你所见,仅仅当前面是美元符号的那个 'foo' 被替换了。另外你也看到,因为美元字符后面的字符序列('foo')完全被'bar'替换掉了,所以美元符号不是匹配结果的一部分。

不使用后行断言而想达到同样结果的实现方式就没这么优雅:

const RE_DOLLAR_PREFIX = /($)foo/g;'$foo %foo foo'.replace(RE_DOLLAR_PREFIX, '$1bar'); // '$bar %foo foo'

如果前继字符也在上一个匹配中时,这种实现方式就不起作用了。

> 'a1ba2ba3b'.match(/(?<=b)a.b/g)[ 'a2b', 'a3b' ]

负向后行断言

负向后行断言(Negative Lookbehind Assertion)仅仅当前位置的前继字符序列与断言 不匹配 时才匹配,并无其他副作用。例如:

const RE_NO_DOLLAR_PREFIX = /(?

如果不使用后行断言的话,要达到同样的结果,是没有其他简单的(一般的)实现方式。

总结

在正则表达式的尾部,使用先行断言最有意义。而在正则表达式的开头,使用后行断言最有意义。

使用先后行断言的用例有:

  • replace()
  • match() (尤其当正则表达式有修饰符 /g)
  • split() (注意 ' b,c' 开始处的空格):
> 'a, b,c'.split(/,(?= )/)[ 'a', ' b,c' ]

除了上述用例外,你也随时可以在正则表达式中使用断言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值