JavaScript正则表达式replace的一个坑
经常听大家说JavaScript是魔法语言,咱却没有什么深刻体会。直到这回踩到这个坑,我终于醒悟了,JavaScript果然来自霍格沃茨!

0x00 踩到坑
昨天咱经过一番考虑后决定将 Python正则表达式细节小记 这篇笔记发到个人博客上。选好文章音乐,复制markdown内容...发布!
按照惯例我检查了一下发布后的文章内容,然后就见到了一个奇怪的现象:

文章内容到一半的时候全被替换成 模板里的HTML 了...
之前调试博客的时候从没遇到过这个问题,我一时就有点摸不着头脑( >﹏<。),但没关系,比对一下原文档就应该知道问题在哪了:

很明显能发现是从$开始被替换了,我心里咯噔一下:怕不是和正则表达式有关!不过在排查正则表达式之前我去改了一下博客后台部分的代码:

结果问题仍然存在,我接着还拿着这样的内容片段进行复现,但没能成功($并没有被替换成其他内容):
test$
$
test$
0x01 坑在哪
到最后,我还是怀疑回了正则表达式,但想来想去还是摸不着头脑,正则表达式和用作替换的字符串有什么关系,$不是用在正则表达式里的吗?而且为什么刻意用$去复现又不行呢?

实在不行只能去求助一下某搜索引擎了:

不查不知道,一查吓一跳,看到有老哥提到了replace函数接收的字符串不仅仅是字符串,我赶紧去MDN查了一下:

原来用作替换的字符串内能包括一些特殊的变量名!
| 变量名 | 代表的值 |
|---|---|
| $$ | 插入一个 "$"。 |
| $& | 插入匹配的子串。 |
| $` | 插入当前匹配的子串左边的内容。 |
| $' | 插入当前匹配的子串右边的内容。 |
| $n | 假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从1开始。如果不存在第 n个分组,那么将会把匹配到到内容替换为字面量。比如不存在第3个分组,就会用“$3”替换匹配到的内容。 |
| $ | 这里Name 是一个分组名称。如果在正则表达式中并不存在分组(或者没有匹配),这个变量将被处理为空字符串。只有在支持命名分组捕获的浏览器中才能使用。 |
现在再回去看文章markdown内容,有一部分我是这样写的:
到了这里,我发现老师说的在```[]```中**被当作普通字符**的元字符只是一部分罢了,主要是 ```*```,```?```,```+```,```{}```,```()```,```$``` 这些元字符。
毫无疑问其中的$\`就被替换为了匹配字串左边的内容,也就是模板的前面一部分,才导致文章被处理成这样。
可以说真的非常魔法了,万万没想到JavaScript竟然在待替换字符串这里内置了一些$变量名的用法。要是我没有想着把这篇小记发到个人博客上,说不定还得要好一阵子才能发现这个问题。
0x02 解决方法
解决方法其实很简单,str.replace(regexp|substr, newSubStr|function)的第二个参数是可以接受一个函数的,而这个函数的 返回值 就被直接用作匹配项替换了,而不是先寻找一遍$变量名。
比如我原来是这样写的:
str.replace(new RegExp('\\{\\[' + from + '\\]\\}','gi'), to);
那么我用箭头函数改写一下就行了:
str.replace(new RegExp('\\{\\[' + from + '\\]\\}','gi'), ()=>to);
其实就相当于:
str.replace(new RegExp('\\{\\[' + from + '\\]\\}','gi'), function(){
return to;
});
关于这个函数传入的参数可以看MDN文档这里的 指定一个函数作为参数

0x03 教训
以后写JavaScript代码的时候还是不能掉以轻心了,说不定在哪个角落还有我不太清楚的魔法。遇到不会或者不清楚的一定要多查文档,不然一旦写进项目里可能就会成为一个遗留的潜在问题。(ノへ ̄、)
JavaScript正则表达式replace的一个坑的更多相关文章
- 关于Javascript splice方法的一个坑。
w3c相关文档:http://www.w3school.com.cn/jsref/jsref_splice.asp bug:购物车计算价格的时候.加商品没问题,减商品的时候价格总是计算错误. 经排查发 ...
- JavaScript的replace方法与正则表达式结合应用讲解
大家好!!今晚在华软G43*宿舍没什么事做,把javascript中replace方法讲解一下,如果讲得不对或不合理是情理之中的事,因为我不是老鸟,也不是菜鸟,我也不知道我当底是什么鸟??呵~~ re ...
- JavaScript 正则表达式——定义,目的,特点,语法,字符串方法,search() ,replace() ,test(),exec()
㈠什么是正则表达式? ⑴正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念. 正则表达式通常被用来检 ...
- JavaScript中sort方法的一个坑(leetcode 179. Largest Number)
在做 Largest Number 这道题之前,我对 sort 方法的用法是非常自信的.我很清楚不传比较因子的排序会根据元素字典序(字符串的UNICODE码位点)来排,如果要根据大小排序,需要传入一个 ...
- javascript正则表达式入门先了解这些
前言 此内容由学习<JavaScript正则表达式迷你书(1.1版)>整理而来(于2020年3月30日看完).此外还参考了MDN上关于Regex和String的相关内容,还有ECMAScr ...
- 【JS】javascript 正则表达式 大全 总结
javascript 正则表达式 大全 总结 参考整理了一些javascript正则表达式 目的一:自我复习归纳总结 目的二:共享方便大家搜索 微信:wixf150 验证数字:^[0-9]*$ 验证n ...
- 理清JavaScript正则表达式--下篇
紧接:"理清JavaScript正则表达式--上篇". 正则在String类中的应用 类String支持四种利用正则表达式的方法.分别是search.replace.match和s ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- js正则表达式replace里有变量的解决方法用到RegExp类
一直比较害怕使用正则表达式,貌似很深奥很复杂的样子,所以在用js操作字符串的时候,我最多使用的是replace.split.substring.indexOf等函数,这些函数有时候需要多次叠加使用,但 ...
随机推荐
- PHP获取当前网址路径
$_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] // 获取来源 function ...
- Linux系列(39) - nohup
nohup 英文全称 no hang up(不挂起),用于在系统后台不挂断地运行命令,退出终端不会影响程序的运行. nohup 命令,在默认情况下(非重定向时),会输出一个名叫 nohup.out 的 ...
- javascript 对象池
* 一个对象池的简单应用 tool tip tootip.html <html> <head> <meta charset="UTF-8"> & ...
- P3515-[POI2011]Lightning Conductor【整体二分,决策单调性】
正题 题目链接:https://www.luogu.com.cn/problem/P3507 题目大意 \(n\)个数字的一个序列\(a\),对于每个位置\(i\)求一个\(p_i\)使得对于任意\( ...
- T-SQL——关于表数据的复制插入
目录 0. 复制表中一列插入到另外一列 1. 复制表结构和数据到自动创建的一张新表中--select into 2. 复制表中一些字段值插入到另外一张表中--insert into 3. 将存储过过程 ...
- Snipaste屏幕截图的使用
什么是Snipaste Snipaste是一款屏幕截图软件 类似于微信的截图 Snipaste使用步骤 百度搜索Snipaste 如图 点击 根据自己电脑系统选择安装 下载完成后 解压到当前文件夹 点 ...
- 感恩笔记之SQL语句操纵数据集基本功能模板
SQL查询_基本功能 一 SQL语句整体架构 SELECT --1 查询数据表 INTO --2 新建数据表 FROM --3 查询数据表 WHERE --4 筛选数据表 ORDER BY --5 排 ...
- 第21篇-加载与存储指令之iload、_fast_iload等(3)
iload会将int类型的本地变量推送至栈顶.模板定义如下: def(Bytecodes::_iload , ubcp|____|clvm|____, vtos, itos, iload , _ ); ...
- xshell连接vmware系统完整版
设置静态ip需要修改文件一共有两个要修改的文件vi /etc/resolv.confvi /etc/sysconfig/network-scripts/ifcfg-eno16777736 第一个文件 ...
- SpringBoot-语言国际化
在resouce下新建i18ni18n 类似的还有k8s在i18n下新建signIn.properties再新建 signIn_zh_CN.properties此时,iden会帮助合并: 现在可以在这 ...