[正则表达式]-JavaScript逆序环视正则语法详解

169 阅读3分钟

环视概念简介

环视(look around)只进行子表达式的匹配,并不占字符,匹配到的内容不进行保存,环视最终的匹配结果就是一个位置,子表达式为零宽度,因此也叫零宽断言(zero-width assertion)

环视按照方向可分为顺序环视(lookahead)和逆序环视(lookbehind)两种,按匹配条件分肯定(positive)和否定(negative)两种,组合起来就是四种模式。

四种组合模式肯定环视(匹配符合条件的内容)否定环视(匹配不符合条件的内容)
顺序环视(从左往右环视)顺序肯定环视 ?=顺序否定环视 ?!
逆序环视(从右往左环视)逆序肯定环视 ?<=逆序否定环视 ?<!

💡记忆方法:问号表示询问,作为开头符号表示询问接下来的条件是否符合预期 (不同于问号在正则放在规则尾部时表达询问前面的内容是否存在)

最直观的就是顺序肯定环视,问号后面紧跟等号,表示询问接下来的内容是否等于指定规则,与之对应的则是使用感叹号表达否定,询问接下来的内容是否不等于指定的规则。

而逆序环视相对于顺序环视的区别就是增加一个小于号,小于号箭头向左,以此来表达“逆序”(因为正则默认的匹配顺序是从左往右),后面的等号或感叹号则与正序环视相同。

JS环视语法兼容性

Safari 对于逆序环视的兼容性较差,仅支持 >=16.4 的版本

caniuse.com/js-regexp-l…

正序环视兼容性则好一些,基本覆盖大部分用户使用的浏览器版本,所以一般不需要考虑兼容性问题。

caniuse.com/?search=loo…

相关材料

兼容性方案

逆序环视是很好的正则语法糖,可以简化很多规则匹配的写法。但由于 Safari 目前对它的兼容性还不太理想,因此如果希望避免因误用该语法而导致运行时报错,需要考虑使用工程化手段在项目编译阶段检测出该语法的误用。

比如可以使用 eslint 插件 eslint-plugin-es 来禁用逆序环视的使用(该插件虽然非 eslint 官方插件,但仓库作者为 eslint 核心维护者)

优点

避免源码中误引入逆序环视,导致 safari/iOS 16.4 以下设备无法使用(比如浏览器白屏,报错如下图)

image.png

缺点

无法检测到 node_modules 内三方包的逆序环视使用(因为一般使用 eslint 只会对项目源码进行检查)

语法替代方案示例

场景需求描述使用逆序环视不使逆序环视
匹配由字母、数字、下划线组成的字符串,下划线不能出现在开始或结束位置^(?!_)[a-zA-Z0-9_]+(?<!_)$^[a-zA-Z0-9]([a-zA-Z0-9_]*[a-zA-Z0-9])?$

逆序环视是很好用的匹配语法,但本质上是编程语言提供的正则语法糖,如果需要兼容暂未支持该语法的使用环境,也可以使用其他方式实现相同的效果,只是没有使用逆序环视那么方便而已。

由于正则是用于匹配规则的语法,因此并没有所谓的通用替代方案,需要根据具体的场景来考虑不依赖逆序环视的匹配方式

相关讨论

学习资料推荐