Javascript中字符串对象有一个方法replace(),它的作用非常强大。这里把它的用法整理一下。
一、方法简介
该方法的签名是:replace([RegExp|String],[String|Function])。
该方法 返回一个新的字符串,但并不改变字符串本身。
该方法接收2个参数,第一个参数可以是字符串,也可以是一个正则表达式;第二个参数可以是一个字符串,也可以是一个函数。其中第2个参数如果是函数,那么用起来是十分强大而且灵活的,不过相对来说也比较难掌握。下面就其用法进行详细说明。
二、基本用法
假如我们有一个字符串中出现了错别字”背景“,需要用”北京“来替换,那么我们可以如下搞定:
var str = "我爱背景*"; str = str.replace("背景","北京"); console.log(str); //输出结果:我爱北京*
这个用法跟C#中的replace()用法别无二致,大家一看就明白。
但是这个用法有个“坑”,看下例:
var str = "我爱背景*,但是背景雾霾太严重"; str = str.replace("背景","北京"); console.log(str); //输出结果:我爱北京*,但是背景雾霾太严重
我们发现,如果字符串str中有多个待替换的子串,比如本例中的“背景”,出现了2次,那么replace()方法只能给我们用目标字符串(北京)替换掉第1次出现的"背景"。如果想把所有的"背景"都给替换了,就必须调用多次。这是我们不能接受的,因为我们无法预知原始字符串中出现了多少个错别字。
幸好,replace()方法还提供了第二种用法,就是使用正则表达式。
三、使用正则表达式
var str = "我爱背景*,但是背景雾霾太严重"; str = str.replace(/背景/g,"北京"); console.log(str); //输出结果:我爱北京*,但是北京雾霾太严重
这里需要说明的是,str.replace(/背景/g,"北京")的第一个参数 ”/背景/g“ 是一个正则表达式,使用/ /的正则写法是JavaScript中正则表达式的字面量写法。在此处,正则表达式的末尾有个g,它表示match源字符串str中所有匹配项。这里如果没有g,那么也只能匹配到第一个错别字”背景“,只有加了这个g,才能匹配到所有的”背景“。
四、正则表达式+function的用法
以上的用法还是比较直观的,但是能实现的功能也比较简单,如果需要做一些复杂的字符串替换运算,那么就需要使用较为高级(复杂)的用法,就是 正则+function 的用法。说白了就是第一参数传一个正则表达式,我们下面称之为RegArg;第二个参数给一个函数,我们下面称之为FuncArg。这也是replace()的核心用法。
讨论这个用法的前提,就是需要对JavaScript的Sring.match()有充分理解。不了解的,可以参考 详解正则表达式匹配方法match() 。
这个用法的本质就是:对str使用RegArg做match()匹配,如果匹配到多项结果(比如使用了全局匹配g,或者分组),那么每一个匹配结果都将执行一次FuncArg函数,并且用该函数的返回值替代源字符串中的匹配项。
这个用法复杂就复杂在这个FuncArg有不同的使用方式,下面做详细介绍。
4.1简单用法,正则表达式不使用分组
var str = \'我爱背景*,但是背景雾霾太严重\'; var re = str.replace(/背景/, function(){ console.log(arguments); return \'北京\'; })
输出结果是
解析:
- 本例的意图是:把源字符串中的‘背景’,替换为‘北京’。
- 正则表达式没有使用全局匹配符g,所以只替换了源字符串中第一个‘背景’子串,FuncArg只执行了一次
- 前面都不难理解,关键是:replace()函数,当第二个参数是一个函数时,这个函数是有参数的,而且这些参数是默认的。需要说明的是,当前这个例子比较简单,所以只有3个匹配项,
-
- arguments[0]是匹配到的子字符串;
- arguments[1]是匹配到的子串的索引位置
- arguments[2]是源字符串本身
4.本例如果想替换所有的‘背景’为‘北京’,只需要让正则表达式后加个g。代码我就不贴出来了,只贴出来输出结果。
我们可以看到,输出了2个Arguments,因为我们使用全局匹配g后,会match到2个项,所以就执行了2次function。第一个跟前边一样,第二个arugments的索引位置是10,因为源字符串中第二个‘背景’的索引是10.
如果就做这样的例子,你可能觉得还不如直接使用: str = str.replace(/背景/g,"北京");
那么就再来一个例子,看看使用function做参数的好处。
这个例子的意图是,把捐款是100元以下的金额数用‘**’来替换掉。
var txt =\'刘菲:50元。张常成:150元。孙玉杰:200元。李明轩:20元。李子豪:1500元。\';
var txt = txt.replace(/\d+/g, function(){
console.log(arguments);
return arguments[0].length > 2 ? arguments[0] : \'**\';
})
console.log(txt);
输出的结果是:
我们可以看到,刘菲和李明轩的捐款被替换成 ** 了。
4.2复杂用法,正则使用分组
var txt =\'刘菲:5万。张常成:5000元。孙玉杰:2000元。李明轩:20万。李子豪:8500元。\';
var txt = txt.replace(/(\d+)(万)/g, function(){
console.log(arguments);
})
- 这个例子的意图是:把所有以“万”为单位的捐款,其金额改为‘元’。比如 :4万,改为40000元
- 这个例子只写了一半,目的是要研究下在正则表达式使用了分组以后arguments的变化
- 输出结果是:
仔细观察arguments结果集,明显比上一个例子多出2项。这些项分别是:
- arguments[0]是匹配到的子字符串;
- arguments[1]是匹配到的第1个分组项
- arguments[2]是匹配到的第2个分组项
- arguments[3]是匹配到的字符串的索引位置
- arguments[4]是源字符串本身
这里正则有2个分组,所以多了匹配到的2个分组项;同理,如果有3个分组,就会多出3个匹配到的分组项。
看懂了这个回调函数的arguments各项代表的意义,下面,我们就来真正的解决问题。
var txt =\'刘菲:5万。张常成:5000元。孙玉杰:2000元。李明轩:20万。李子豪:8500元。\';
var txt = txt.replace(/(\d+)(万)/g, function(){
console.log(arguments);
return arguments[1] + \'0000\' + \'元\';
})
console.log(txt);
输出结果是: