zoukankan      html  css  js  c++  java
  • 先行断言和后行断言

    后行断言

    JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。目前,有一个提案,引入后行断言,V8 引擎 4.9 版已经支持。

    ”先行断言“指的是,x只有在y前面才匹配,必须写成/x(?=y)/。比如,只匹配百分号之前的数字,要写成/d+(?=%)/。”先行否定断言“指的是,x只有不在y前面才匹配,必须写成/x(?!y)/。比如,只匹配不在百分号之前的数字,要写成/d+(?!%)/

    /d+(?=%)/.exec('100% of US presidents have been male')  // ["100"]
    /d+(?!%)/.exec('that’s all 44 of them')                 // ["44"]
    

    上面两个字符串,如果互换正则表达式,就不会得到相同结果。另外,还可以看到,”先行断言“括号之中的部分((?=%)),是不计入返回结果的。

    “后行断言”正好与“先行断言”相反,x只有在y后面才匹配,必须写成/(?<=y)x/。比如,只匹配美元符号之后的数字,要写成/(?<=$)d+/。”后行否定断言“则与”先行否定断言“相反,x只有不在y后面才匹配,必须写成/(?<!y)x/。比如,只匹配不在美元符号后面的数字,要写成/(?<!$)d+/

    /(?<=$)d+/.exec('Benjamin Franklin is on the $100 bill')  // ["100"]
    /(?<!$)d+/.exec('it’s is worth about €90')                // ["90"]
    

    上面的例子中,“后行断言”的括号之中的部分((?<=$)),也是不计入返回结果。

    下面的例子是使用后行断言进行字符串替换。

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

    上面代码中,只有在美元符号后面的foo才会被替换。

    “后行断言”的实现,需要先匹配/(?<=y)x/x,然后再回到左边,匹配y的部分。这种“先右后左”的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。

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

    /(?<=(d+)(d+))$/.exec('1053') // ["", "1", "053"]
    /^(d+)(d+)$/.exec('1053') // ["1053", "105", "3"]
    

    上面代码中,需要捕捉两个组匹配。没有"后行断言"时,第一个括号是贪婪模式,第二个括号只能捕获一个字符,所以结果是1053。而"后行断言"时,由于执行顺序是从右到左,第二个括号是贪婪模式,第一个括号只能捕获一个字符,所以结果是1053

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

    /(?<=(o)d1)r/.exec('hodor')  // null
    /(?<=1d(o))r/.exec('hodor')  // ["r", "o"]
    

    上面代码中,如果后行断言的反斜杠引用(1)放在括号的后面,就不会得到匹配结果,必须放在前面才可以。因为后行断言是先从左到右扫描,发现匹配以后再回过头,从右到左完成反斜杠引用。

  • 相关阅读:
    cocos2d-x避免手动修改android.mk文件来编译
    Android.mk详解
    cocos2dx 安卓编译问题收集
    Mac下部署Android开发环境附加NDK
    SpringMVC关于json、xml自动转换的原理研究
    SpringMVC的拦截器
    Spring3中的mvc:interceptors标签配置拦截器
    Spring常用的接口和类(三)
    Spring常用的接口和类(二)
    LeetCode:寻找旋转排序数组中的最小值【153】
  • 原文地址:https://www.cnblogs.com/justart/p/8158531.html
Copyright © 2011-2022 走看看