之前一直以为对js正则表达式的最最基本的使用已经掌握了,结果今天在想要使用String.replace来达到将匹配到的内容替换为匹配到的内容中的一部分再加以转换操作得到的结果时(看起来有点晕,不好意思,我自己都觉得说的很乱,不过不知道该怎么更好的表述),发现不会啊,特写此篇来记录一下今天弥补的坑!
参考资料
W3School JavaScript replace() 方法
基本使用
stringObject.replace(regexp/substr,replacement)
详细的使用方法,可以参考网上其他很多优秀的文章,这篇文章主要讲述当replacement是函数时的使用。
说明
字符串 stringObject 的 replace() 方法执行的是查找并替换的操作。它将在 stringObject 中查找与 regexp 相匹配的子字符串,然后用 replacement 来替换这些子串。
如果 regexp 具有全局标志 g,那么 replace() 方法将替换所有匹配的子串。否则,它只替换第一个匹配子串。
replacement 可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。但是 replacement 中的$
字符具有特定的含义。如下表所示,它说明从模式匹配得到的字符串将用于替换。
字符 | 替换文本 |
---|---|
$1、$2、…、$99 | 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。 |
$& | 与 regexp 相匹配的子串。 |
$` | 位于匹配子串左侧的文本。 |
$’ | 位于匹配子串右侧的文本。 |
$$ | 直接量符号。 |
注: 说明里面的内容都是从参考链接里粘贴来的,当然重点是下面的!
函数 replacement
我之前只知道当replacement是字符串的时候,$1</code>~<code>$99
即是子表达式匹配到的文本,这个说法也不是很易理解,举个例子吧。
去网上随便找了个邮箱的正则表达式
var reg = /^(\w+)([-+.](\w+))*@(\w+)([-.](\w+))*\.(\w+)$/g;
测试邮箱 email:
1. 123456789@email.com
2. 1234-56789@email.js.com
3. 123-456.789@email.js.regexp.com
用reg.exec(email)试一下,结果分别为
["123456789@email.com", "123456789", undefined, undefined, "email", undefined, undefined, "com"]
["1234-56789@email.js.com", "1234", "-56789", "56789", "email", ".js", "js", "com"]
["123-456.789@email.js.regexp.com", "123", ".789", "789", "email", ".regexp", "regexp", "com"]
可以看出,返回值为一个数组,且数组的大小是一致的,都为小括号的个数 + 1。当子表达式是用*
或者+
来修饰时,返回值中只会在对应位置保留最后一个匹配到的内容。
分别用 $i
来替换整个匹配文本,用第三个email来测试
var res = reg.exec(email);
for (var i = 1; i < res.length; ++i) {
var str = email.replace(reg, '$' + i);
console.log(str);
}
输出结果:
123
.789
789
email
.regexp
regexp
com
即 String.replace 的replacement 中,$i
对应于reg.exec返回值的下标(i >= 1)。
这里的replacement是字符串,可以直接写在String.replace的第二个参数那里。
那么当replacement为函数时,要怎么使用$i
,这个就是我今天刚填的坑。
replacement函数在被调用时,我们可以用arguments获取所有实参,这里就包括了所有的$i
!还是拿第三个email来测试一下
email.replace(reg, function() {
console.log(arguments);
});
输出结果
["123-456.789@email.js.regexp.com", "123", ".789", "789", "email", ".regexp", "regexp", "com", 0, "123-456.789@email.js.regexp.com"]
前8个值和reg.exec(email)的结果完全相同,最后两个分别为匹配内容的首字符在原字符串stringObject中的下标和完整的原字符串stringObject。
这样就可以达到我最初的目的了!
举个例子
比如要将字符串中所有的直角坐标(x,y)转换为极坐标(ρ,θ)。
var str = "线段的两个端点分别为(1,1)和(3,4)";
var reg = /\((\d+),(\d+)\)/g;
var res = str.replace(reg, function() {
var x = parseInt(arguments[1]);
var y = parseInt(arguments[2]);
var l = Math.sqrt(x * x + y * y);
var rad = Math.atan2(y, x);
return "(" + l + "," + rad + ")";
});
console.log(res);
输出结果
"线段的两个端点分别为(1.4142135623730951,0.7853981633974483)和(5,0.9272952180016122)"
以上所有,如有错误,麻烦指出,我会及时更改的。