如何将含lookbehind的JS正则改写为兼容iOS的无后行断言版本
兼容iOS WebKit内核的正则改写方案
不兼容根因
原正则/(?<!\\)\w?\$.+?(?<!\\)\$/ 无法在低版本iOS浏览器运行,是因为其中用到了两处负向后顾断言(Lookbehind)。该语法直到WebKit 16.4版本才被支持,大量iOS 15及更早版本的Safari、基于WebKit内核的Chrome会直接抛出语法错误,完全无法执行匹配逻辑。
改写核心逻辑
向后顾断言的作用仅仅是判断当前位置的$符号前面有没有紧邻的反斜杠转义符,这个判断不需要依赖任何不兼容的高级语法——我们可以把$前面紧邻的字符通过捕获组抓取,等正则匹配完成后做两个简单的字符串判断,就能100%复现原规则的匹配效果。相比各种靠分支嵌套、零宽断言绕兼容的写法,这种方案用到的全是JS原生支持了几十年的基础正则语法,不会有任何隐藏的兼容问题,能覆盖所有iOS WebKit版本。
具体实现
- 首先编写全兼容的基础匹配正则,全程只使用WebKit全版本都支持的基础语法:
正则结构拆解:/(\\?)\w?\$(.+?)(\\?)\$/g- 第一捕获组
(\\?):抓取左边界$前面紧邻的可选反斜杠 \w?:保留原正则中“左$前面允许出现0个或1个单词字符”的规则\$:匹配左边界$(.+?):非贪婪匹配两个$之间的任意文本,和原逻辑完全对齐- 第三捕获组
(\\?):抓取右边界$前面紧邻的可选反斜杠 \$:匹配右边界$
- 第一捕获组
- 拿到正则匹配结果后,做两个极简校验即可复现原lookbehind的判断逻辑:
- 若第一捕获组内容为
\\,说明这个左$前面带转义符,直接丢弃该匹配 - 若第三捕获组内容为
\\,说明这个右$前面带转义符,直接丢弃该匹配
- 若第一捕获组内容为
匹配效果验证
用典型测试文本跑一遍逻辑:
这是普通文本\$带转义符的$内容$这是合法的公式内容$,后面的\$不是合法右边界$另一组合法公式$
经过匹配+校验后,会准确提取出两处合法匹配:$这是合法的公式内容$、$另一组合法公式$,所有被转义的$都会被自动跳过,和原正则的运行效果完全一致。
注:该方案没有引入额外的性能损耗,两个捕获组的判断是极轻量的字符串比较,完全不影响大文本下的匹配速度。
内容的提问来源于stack exchange,提问作者Jon Doe
相关产品推荐
相关产品推荐

