这篇文章上次修改于 846 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
有幸认识到了正则一个很有趣的特性,叫做「反向断言」,相对而言也有一个正向断言,举个例子:
// Paul666
"Paul666".match(/Paul?6+/)
// Paul
"Paul666".match(/Paul(?=6+)/)
// 666
"Paul666".match(/(?<=Paul)6+/)
解析
他们分别的使用情形很简单:
- 匹配字符串里面包含
Paul
,且后面包含至少一个6
的部分 - 匹配字符串里面包含
Paul
,且后面包含至少一个6
的部分,并提取掉后面的所有6
- 匹配字符串里面包含
Paul
,且后面包含至少一个6
的部分,并提取掉前面的Paul
这个例子确实比较简单,你可能觉得没啥特别的作用。我在项目里面使用到「反向断言」,主要是为了把一段 URL 里面的 ID 提取出来。
从 URL https://live.paul.ren/106789266720369/videos/224220006785235 提取出 224220006785235,使用纯 ID 形式 224220006785235 也能匹配成功
于是我首先写的正则是:
return url.match(/(?<=videos\/)[0-9]+|^[0-9]+/);
第一个条件只需要满足 videos
在 ID 的前面,然后「反向断言」就 OK,|
后面的就是纯数字匹配啦~
兼容性
这个功能确实很好用,但是等我实测上线到 Staging 环境之后才发现,这个特性无法在 Safari 下正常工作。我电脑所安装的版本是:14.1.2 (15611.3.10.1.5, 15611)
SyntaxError: Invalid regular expression: invalid group specifier name
既然解决不了 Safari 兼容性垃圾的问题,那就只能换个思路写了呗!于是得到了这个:
// ! Safari 不支持反向断言,只能换个思路解决
const _val = ev.target.value;
let _match = _val.match(/videos\/[0-9]+/);
if(_match ?. [0]){
return _match[0].replace("videos/", "")
}
_match = _val.match(/^[0-9]+/);
if(_match ?. [0]){
return _match[0];
}
就是先看看得到的 URL 符不符合要求,再通过替换为空字符串的方式(也可以用 substr
截取)得到结果。第二个匹配就是检查是否为纯数字,这个就不用详细解释了吧...
没有评论