惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
小众软件
小众软件
有赞技术团队
有赞技术团队
月光博客
月光博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MyScale Blog
MyScale Blog
Engineering at Meta
Engineering at Meta
Stack Overflow Blog
Stack Overflow Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MongoDB | Blog
MongoDB | Blog
WordPress大学
WordPress大学
J
Java Code Geeks
罗磊的独立博客
V
Visual Studio Blog
雷峰网
雷峰网
H
Help Net Security
T
The Blog of Author Tim Ferriss
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
大猫的无限游戏
大猫的无限游戏
F
Fortinet All Blogs

zodream梦想开源/个人编程日记

文件解析笔记-zodream梦想开源/个人编程日记 密码本开发笔记之读写与保存-zodream梦想开源/个人编程日记 SkiaSharp 把 pixel byte[] 转成 SKBitmap-zodream梦想开源/个人编程日记 nas 使用 Docker 安装 gogs-zodream梦想开源/个人编程日记 复制 android 手机中的文件到电脑-zodream梦想开源/个人编程日记 周报:寻找优质的周刊-zodream梦想开源/个人编程日记 开发日志:对Markdown的代码块新增引用来源支持-zodream梦想开源/个人编程日记 周报:怎么写技术类的教程文章-zodream梦想开源/个人编程日记 css display:flex 布局尺寸超出问题-zodream梦想开源/个人编程日记 周报:SEO优化的思考-zodream梦想开源/个人编程日记 Edge 浏览器不适用 Edge Image Viewer 打开图片 -zodream梦想开源/个人编程日记 SEO 学习笔记(一) 内容来源-zodream梦想开源/个人编程日记 PHP 实现双因素身份认证(2FA)-zodream梦想开源/个人编程日记 WPF MVVM 获取List 多选数据-zodream梦想开源/个人编程日记 Burp Suite 抓包-zodream梦想开源/个人编程日记 使用 indexnow 注意事项-zodream梦想开源/个人编程日记 Godot 使用字体图标 例如: Iconfont、FontAwesome-zodream梦想开源/个人编程日记 angular 15 对指定页面进行访问限制-zodream梦想开源/个人编程日记 CSS 使用 column-count 实现瀑布流出现内容分割的解决办法-zodream梦想开源/个人编程日记 input 确认按键事件在手机端不生效-zodream梦想开源/个人编程日记 C# 使用socket 进行通讯-zodream梦想开源/个人编程日记 Maui开发中Windows应用开启管理员权限-zodream梦想开源/个人编程日记 Maui 中自定义控件-zodream梦想开源/个人编程日记 angular 14 使用 ng-template 实现tree 结构显示-zodream梦想开源/个人编程日记 c# 动态安装和卸载dll-zodream梦想开源/个人编程日记 慎用 CompositionTarget.Rendering-zodream梦想开源/个人编程日记 c# 重写 c++ 程序笔记:数据初始化-zodream梦想开源/个人编程日记 源码编译 aseprite-zodream梦想开源/个人编程日记 记录一下字符串分隔split各语言之间的不同-zodream梦想开源/个人编程日记 c# Gzip解码无头内容-zodream梦想开源/个人编程日记
js 实现一个正则替换-zodream梦想开源/个人编程日记
zodream · 2021-06-04 · via zodream梦想开源/个人编程日记

js 实现一个正则替换

代码

/**
 * 正则匹配替换
 * @param content 
 * @param pattern 
 * @param cb 
 * @returns 
 */
export function regexReplace(content: string, pattern: RegExp, cb: (match: RegExpExecArray) => string): string {
    if (content.length < 1) {
        return content;
    }
    const matches: RegExpExecArray[] = [];
    let match: RegExpExecArray|null;
    while (null !== (match = pattern.exec(content))) {
        matches.push(match as RegExpExecArray);
    }
    const block: string[] = [];
    for (let i = matches.length - 1; i >= 0; i--) {
        match = matches[i];
        block.push(content.substr(match.index + match[0].length));
        block.push(cb(match));
        content = content.substr(0, match.index);
    }
    return content + block.reverse().join('');
}

12345678910111213141516171819202122232425

原理

  1. 先获取所有的匹配结果,存入一个临时数组中
  2. 倒序执行回调方法获取替换的内容
  3. 按照匹配到的位置,截断字符串,把匹配到的部分根据长度去除,然后按倒序和替换的字符串存入一个数组,
  4. 颠倒数组顺序连接即最终结果

疑问

Q:为什么不在匹配时边匹配边替换?

A:原本我这样做的,发现匹配结果出错了,有些没匹配到。因为exec 匹配时正则表达式会记住最后的匹配位置,如果原本的内容长度变化;,就会导致这个位置不正确。

Q:为什么要截断字符串?

A: 使用字符串替换会搜索全部,多一些不必要的操作;截断存入数组,就是想最后一起做拼接。

Q: 为什么要倒序替换?

A: 因为正序截取的话会导致匹配结果中的位置要进行改变。

转载请保留原文链接: https://zodream.cn/blog/id/208.html