了解 ECMAScript RegExp 断言

前言

JavaScript 语言的正则表达式ES5只支持先行断言lookahead)和先行否定断言negative lookahead),不支持后行断言lookbehind)和后行否定断言negative lookbehind)。


先行断言

基础说明

先行断言lookahead)指的是,x只有在y前面才匹配,必须写成/x(?=y)/

先行断言括号之中的部分((?=%)),是不计入返回结果的。


举例

只匹配百分号之前的数字

((log) => {
    const regex1 = /\d+(?=%)/;
    const regex2 = /\d+(?!%)/;
    const string = '100% of US presidents have been male';

    log(regex1.exec(string)); // ["100", index: 0, input: "100% of US presidents have been male", groups: undefined]
    log(regex2.exec(string)); // ["10", index: 0, input: "100% of US presidents have been male", groups: undefined]
})(console.log)


先行否定断言

基础说明

先行否定断言negative lookahead)指的是,x只有不在y前面才匹配,必须写成/x(?!y)/

先行否定断言括号之中的部分((?!%)),是不计入返回结果的。


举例

只匹配不在百分号之前的数字

((log) => {
    const regex1 = /\d+(?=%)/;
    const regex2 = /\d+(?!%)/;
    const string = 'that’s all 44 of them';

    log(regex1.exec(string)); // null
    log(regex2.exec(string)); // ["44", index: 11, input: "that’s all 44 of them", groups: undefined]
})(console.log)


后行断言

基础说明

ES2018 引入后行断言lookbehind),V8 引擎 4.9 版(Chrome 62)已经支持。

后行断言正好与先行断言相反,x只有在y后面才匹配,必须写成/(?<=y)x/


举例

美元匹配

只匹配美元符号之后的数字

((log) => {
    const regex1 = /(?<=\$)\d+/;
    const regex2 = /(?<!\$)\d+/;
    const string = 'Benjamin Franklin is on the $100 bill';

    log(regex1.exec(string)); // ["100", index: 29, input: "Benjamin Franklin is on the $100 bill", groups: undefined]
    log(regex2.exec(string)); // ["00", index: 30, input: "Benjamin Franklin is on the $100 bill", groups: undefined]
})(console.log)


字符串替换

使用后行断言进行字符串替换

((log) => {
    const RE_DOLLAR_PREFIX_1 = /(?<=\$)foo/g;
    const RE_DOLLAR_PREFIX_2 = /(?<!\$)foo/g;
    const REPLACE_STR = 'bar';
    const string = '$foo %foo foo';

    // 只有在美元符号后面的foo才会被替换
    log(string.replace(RE_DOLLAR_PREFIX_1,REPLACE_STR)); // $bar %foo foo
    // 只有不在美元符号后面的foo才会被替换
    log(string.replace(RE_DOLLAR_PREFIX_2,REPLACE_STR)); // $foo %bar bar
})(console.log)

tip

组匹配顺序

后行断言的实现,需要先匹配/(?<=y)x/x,然后再回到左边,匹配y的部分。

这种先右后左的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。

首先,后行断言组匹配,与正常情况下结果是不一样的。

((log) => {
    const regex1 = /(?<=(\d+)(\d+))$/;
    const regex2 = /^(\d+)(\d+)$/;
    const string = '1053';

    log(regex1.exec(string)); // ["", "1", "053", index: 4, input: "1053", groups: undefined]
    log(regex2.exec(string)); // ["1053", "105", "3", index: 0, input: "1053", groups: undefined]
})(console.log)

上面代码中,需要捕捉两个组匹配

没有后行断言时,第一个括号是贪婪模式,第二个括号只能捕获一个字符,所以结果是1053

后行断言时,由于执行顺序是从,第二个括号是贪婪模式,第一个括号只能捕获一个字符,所以结果是1053


反斜杠规范

后行断言反斜杠引用,也与通常的顺序相反,必须放在对应的那个括号之前。

((log) => {
    const regex1 = /(?<=(o)d\1)r/;
    const regex2 = /(?<=\1d(o))r/;
    const string = 'hodor';

    log(regex1.exec(string)); // null
    log(regex2.exec(string)); // ["r", "o", index: 4, input: "hodor", groups: undefined]
})(console.log)

上面代码中,如果后行断言反斜杠引用(\1)放在括号的后面,就不会得到匹配结果,必须放在前面才可以。

因为后行断言是先从扫描,发现匹配以后再回过头,从完成反斜杠引用。


后行否定断言

基础说明

后行否定断言negative lookbehind)则与先行否定断言相反,x只有不在y后面才匹配,必须写成/(?<!y)x/


举例

只匹配不在美元符号后面的数字

((log) => {
    const regex1 = /(?<=\$)\d+/;
    const regex2 = /(?<!\$)\d+/;
    const string = 'it’s is worth about €90';

    log(regex1.exec(string)); // null
    log(regex2.exec(string)); // ["90", index: 21, input: "it’s is worth about €90", groups: undefined]
})(console.log)


今日学习总结


作者:小又又
链接:https://juejin.im/post/5ecd38846fb9a047cc156d27
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值