正则零宽断言的理解

正则匹配中,除了文本的匹配外,还有位置匹配。

因为位置匹配不会匹配任何实际的文本,只是匹配文本中的位置,所以也称为锚点(Anchors)、零长度断言 或者 零宽断言 (Zero-Width Assertions)。
结合这几个名字,这个概念的含义已经很明显。

零宽断言是一种零宽度的匹配,它匹配的内容不会保存到匹配结果中,也不会占用index宽度,最终匹配的结果只是一个位置

简单的说,它用于查找在某些内容之前或之后的东西(但返回结果并不包括这些内容)

JavaScript提供了如下的零宽断言:

零宽断言 意义
^ 匹配输入的开始。
$ 匹配输入的结束。
\b 匹配一个词的边界。
\B 匹配一个非单词边界。
(?=p) 肯定顺序环视
(?!p) 否定顺序环视
(?<=p) 肯定逆序环视
(?<!p) 否定逆序环视

js的负向零宽断言是ES2018才支持的,同时支持的还有,命名分组和dotAll(.能匹配换行符)

Lookbehind assertion: (?<=...), (?<!...) (负向零宽断言) chrome 62 safari 16.4 

function getPrice(label) {
    return /(?<=\$)\d+(?:\.\d*)?/.exec(label)?.[0];
}

getPrice("$10.53"); // "10.53"
getPrice("10.53"); // undefined

safari又拉胯,对于要兼容safari的情况,可以使用折中方案

1. 字符串和正则同时反转,然后匹配

2. 使用前置可空组判断(推荐,看起来简单一些)

前端匹配的字符串用一个组保存,通过判断这个组是否存在来处理

匹配所有前面不是ba的ll

var newString = "Fall ball bill balll llama".replace(/(ba)?ll/g,
   function($0,$1){ return $1 ? $0 : "[match]";});
// Fa[match] ball bi[match] balll [match]ama

ES2018同时支持的还有,命名分组和dotAll(.能匹配换行符)

Named capture groups(命名分组捕获) chrome 64 safari 11.1 

const t = '2020-01-23'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
console.log(t.groups.year)
console.log(t.groups.month)
console.log(t.groups.day)

 

参考:

实现javaScript 正则表达式的反向预查

JavaScript 与正则表达式 -- 位置匹配

JavaScript 正则之零宽断言详解|8月更文挑战

【正则表达式系列】零宽断言

posted @ 2023-11-20 15:42  全玉  阅读(65)  评论(0编辑  收藏  举报