• JS正则②—具名组匹配、先行断言、后行断言


     1.具名组匹配

    正则表达式使用圆括号进行组匹配

    const RE_DATE = /(d{4})-(d{2})-(d{2})/
    
    const matches = RE_DATE.exec('1995-06-20')
    
    console.log(matches);

    上面代码中,正则表达式中有三组圆括号。使用exec()方法,就可以将这三组匹配结果提取出来。

     这样的一个问题就是,每一组的匹配含义不容易看出来,而且只能使用数字需要(如:match[0])表示出来,要是组的顺序变了,引用的时候就必须修改序号。

      ES2018引入了具名组匹配(Named Capture Group),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。

    const RE_DATE = /(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/
    
    const matches = RE_DATE.exec('1995-06-20')
    
    console.log(matches);

     上面的代码中:?<xxx>的作用就是为这个匹配定义一个组名,在匹配的groups属性中可以查看到匹配的组名

    这里可以使用解构赋值直接从匹配结果上为变量赋值。

    2.先行断言 & 后行断言

     (1)先行断言

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

    示例:

    const pat1 = /d+(?=%)/
    const match1 = pat1.exec('100% of US presidents have been male')
    console.log(match1); // ['100']
    
    const pat2 = /d+(?!%)/
    const match2 = pat2.exec('that’s all 44 of them, aaa 12% bbb')
    console.log(match2);  // ['44']

    (2)后行断言

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

    示例:

    const pat1 = /(?<=$)d+/
    const match1 = pat1.exec('Benjamin Franklin is on the $100 bill')
    console.log(match1); // ['100']
    
    const pat2 = /(?<!$)d+/
    const match2 = pat2.exec('it’s is worth about €90')
    console.log(match2);  // ['90']

    说明:

    • 先行断言与后行断言中()内的部分都不计入返回结果

    (3)使用先行断言或后行断言进行字符串替换

    示例:

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

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

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

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

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

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

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

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

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

  • 相关阅读:
    python网络爬虫(1)静态网页抓取
    博弈论的一些例子
    虚机Linux最小系统下安装图形界面,与yum配置
    主成分分析法详解(PCA)
    吴恩达机器学习私人总结(3)神经网络
    HttpServletRequest & HttpServletResponse
    编译原理复习
    Http协议 & Servlet
    分享一下HttpWatch 10 pro 带lic激活文件
    基于Storm的WordCount
  • 原文地址:https://www.cnblogs.com/codexlx/p/14421545.html
Copyright © 2020-2023  润新知