字符串的replace方法应用浅析


Posted in Javascript onDecember 06, 2011

这两个参数都是必须的,replace() 方法的参数 replacement 可以是函数而不是字符串。在这种情况下,每个匹配都调用该函数,它返回的字符串将作为替换文本使用。该函数的第一个参数是匹配模式的字符串。接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或多个这样的参数。接下来的参数是一个整数,声明了匹配在 stringObject 中出现的位置。最后一个参数是 stringObject 本身。对于replacement是函数的情况,给我们提供了很大的便利。

这有一个很简单的交换两个单词顺序的例子,如果不用repalce可以这么做:

(function(){ 
var str = 'click dblclick'; 
var result = str.split(/\b/).reverse().join('') 
console.log(result); 
})()

这么做略显麻烦,用replace处理则显得清爽许多:
(function(){ 
var str = 'click dblclick'; 
var result = str.replace(/\b(\w+)(\s+)(\w+)\b/,'$3$2$1'); 
console.log(result); 
})();

再看另一个例子——给数字加上千分位:
(function(){ 
var number = 12345678900; 
var result = (''+number).replace(/(\d)(?=(\d{3})+$)/g,'$1,'); 
console.log(result); 
})();

不过现在要扯的是replacement作为函数的用法,所以多此一举的把上面的形式改成函数的形式:

(function(){ 
var str = 'click dblclick'; 
var result = str.replace(/\b(\w+)(\s+)(\w+)\b/,function(all,$1,$2,$3){ 
return $3+$2+$1; 
}); 
console.log(result); 
})(); (function(){ 
var number = 12345678900; 
var result = (''+number).replace(/(\d)(?=(\d{3})+$)/g,function(all,$1){ 
return $1 + ','; 
}); 
console.log(result); 
})();

所以replace无非是捕获匹配的项然后经过处理,作为返回值进行替换,只不过是函数的比较给力。
下面看一个比较实用的例子,大多数语言都有的格式化输出,比如C语言的printf:
(function(){ 
var str = '%s may have gone, but there is a time of %s'; 
var result = str.replace(/(%s)/g,function(){ 
return 'replacement'; 
}) 
console.log(result); 
})()

这里有个问题就是,%s都是一样的,替换出来都是一样的,而且我们只能按照顺序来判断被替换的是哪一部分,如果添加一段,那么后面所有的都得变。所以我们得传个变量进去。
(function(){ 
var array = ['Swallows','return']; 
var i = 0; 
var str = '%s may have gone, but there is a time of %s'; 
var result = str.replace(/(%s)/g,function(){ 
return array[i++]; 
}) 
console.log(result); 
})(); 
(function(){ 
var str = '#{what} may have gone, but there is a time of #{how}'; 
var obj = { 
what : 'Swallows', 
how : 'return' 
} 
var result = str.replace(/(?:#{(\w+)})/g,function(all,$1){ 
return obj[$1]; 
}) 
console.log( result); 
})();

显然用对象的方法要靠谱一点。

同时,js并没有那么严格的类型要求,所以,%s这种形式也成为了局限。直接摈弃,换成我们容易理解的形式。

伪装成函数的样子就是:

(function(){ 
function gsub(str,replaceObj){ 
return str.replace(/(?:#{(\w+)})/g,function(all,$1){ 
return replaceObj[$1]; 
}) 
} 
console.log('gsub结果:',gsub('#{what} may have gone, but there is a time of #{how}',{ 
what : 'Swallows', 
how : 'return' 
})) 
})();

上面的gsub借用了Prototype中的gsub方法名字,虽然Prototype中的gsub并不是用的replace,但是形式上还是很像的。

现在面临的一个问题是:

#{what}这种形式的冲突问题,有可能字符串里面刚好就有这种形式的字符串,如果不作处理,后果大家都懂的。

第一种解决办法:正则里面有转义字符,我们也可以有,所以我们干脆在不需要的替换的部分前面加上'\'

第二种解决办法:让使用者自定义一个标志来替换#{}的标志,从而避免冲突。

看第一种方法:

(function(){ 
var str = '#{what} may have gone, but there is a time of #{how},\\#{reserve}'; 
function gsub(str,replaceObj){ 
return str.replace(/(^|.)(?:#{(\w+)})/g,function(all,$1,$2){ 
if($1 == '\\'){ 
return '#{' + $2 +'}'; 
} 
return $1 + replaceObj[$2]; 
}) 
} 
console.log('gsub结果:',gsub(str,{ 
what : 'Swallows', 
how : 'return' 
})) 
})();

上面需要注意的就是'\'在字符串中也是转义字符,写的时候也需要转义。

第二种方法:

我们把'#{what}'换成<%what%>的形式。

(function(){ 
function gsub(str,replaceObj,regexp){ 
regexp = regexp || /(?:#{(\w+)})/g; 
return str.replace(regexp,function(all,$1){ 
return replaceObj[$1]; 
}) 
} 
var str = '<%what%> may have gone, but there is a time of <%how%>,#{reserve}'; 
console.log('gsub结果:',gsub(str,{ 
what : 'Swallows', 
how : 'return' 
},/(?:<%(\w+)%>)/g)) 
})();

现在把gsub挂到String的原型上面
String.prototype.gsub = function(replaceObj,regexp){ 
regexp = regexp || /(^|.)(?:(#{)(\w+)(}))/g; 
return this.replace(regexp,function(all,$1,$2,$3,$4){ 
if($1 == '\\'){ 
return $2+$3+$4; 
} 
return $1 + replaceObj[$3] ; 
}) 
} 
var str = '<%what%> may have gone, but there is a time of <%how%>,\\<%how%>,#{how}'; 
var obj = { 
what : 'Swallows', 
how : 'return' 
} 
console.log('测试1:',str.gsub(obj,/(^|.)(?:(<%)(\w+)(%>))/g)); 
//Swallows may have gone, but there is a time of return,<%how%>,#{how} 
console.log('测试2:',str.gsub(obj)); 
//<%what%> may have gone, but there is a time of <%how%>,\<%how%>,return

嘿嘿,貌似和Prototype中的gsub很像了,不过Prototype中的gsub复杂一些,原理也不一致,熟悉一下,待会再仔细分析Prototype中的gsub方法。
Javascript 相关文章推荐
caller和callee的区别介绍及演示结果
Mar 10 Javascript
js导出table到excel同时兼容FF和IE示例
Sep 03 Javascript
Flexigrid在IE下不显示数据的处理的解决方法
Oct 24 Javascript
json字符串之间的相互转换示例代码
Aug 21 Javascript
node.js 使用ejs模板引擎时后缀换成.html
Apr 22 Javascript
利用JavaScript脚本实现滚屏效果的方法
Jul 07 Javascript
vue.js初学入门教程(1)
Nov 03 Javascript
Angular ui.bootstrap.pagination分页
Jan 20 Javascript
jQuery实现鼠标响应式透明度渐变动画效果示例
Feb 13 jQuery
详解axios中封装使用、拦截特定请求、判断所有请求加载完毕)
Apr 09 Javascript
微信小程序防止多次点击跳转和防止表单组件输入内容多次验证功能(函数防抖)
Sep 19 Javascript
JavaScript模拟实现网易云轮播效果
Apr 04 Javascript
js滚动条回到顶部的代码
Dec 06 #Javascript
javascript检测浏览器flash版本的实现代码
Dec 06 #Javascript
javascript 随机展示头像实现代码
Dec 06 #Javascript
jQuery中需要注意的细节问题小结
Dec 06 #Javascript
jQuery load方法用法集锦
Dec 06 #Javascript
基于JQuery实现的类似购物商城的购物车
Dec 06 #Javascript
使用Jquery来实现可以输入值的下拉选单 雏型
Dec 06 #Javascript
You might like
十天学会php之第九天
2006/10/09 PHP
php socket方式提交的post详解
2008/07/19 PHP
php使用exec shell命令注入的方法讲解
2013/11/12 PHP
PHP中new static()与new self()的区别异同分析
2014/08/22 PHP
php中fsockopen用法实例
2015/01/05 PHP
Yii2选项卡的简单使用
2017/05/26 PHP
详解PHP如何更好的利用PHPstorm的自动提示
2017/08/18 PHP
PHP实现双链表删除与插入节点的方法示例
2017/11/11 PHP
ie和firefox中img对象区别的困惑
2006/12/27 Javascript
带左右箭头图片轮播的JS代码
2013/12/18 Javascript
jQuery实现点击该行即可删除HTML表格行
2014/10/17 Javascript
微信小程序 Tab页切换更新数据
2017/01/05 Javascript
使用jQuery实现简单的tab框实例
2017/08/22 jQuery
shiro授权的实现原理
2017/09/21 Javascript
基于wordpress的ajax写法详解
2018/01/02 Javascript
Vue隐藏显示、只读实例代码
2018/07/18 Javascript
基于Koa(nodejs框架)对json文件进行增删改查的示例代码
2019/02/02 NodeJs
[02:32]DOTA2完美大师赛场馆静安体育中心观赛全攻略
2017/11/08 DOTA
pycharm 使用心得(九)解决No Python interpreter selected的问题
2014/06/06 Python
用C++封装MySQL的API的教程
2015/05/06 Python
python和pygame实现简单俄罗斯方块游戏
2021/02/19 Python
获取python的list中含有重复值的index方法
2018/06/27 Python
Python3 执行Linux Bash命令的方法
2019/07/12 Python
Keras 加载已经训练好的模型进行预测操作
2020/06/17 Python
Python3如何使用多线程升程序运行速度
2020/08/11 Python
里程积分管理买卖交换平台:Points.com
2017/01/13 全球购物
Hotels.com爱尔兰:全球酒店预订
2017/02/24 全球购物
严选全球尖货,立足香港:Bonpont宝盆
2018/07/24 全球购物
巴基斯坦购物网站:Goto
2019/03/11 全球购物
销售经理工作职责范文
2013/12/03 职场文书
党在我心中的演讲稿
2014/09/13 职场文书
2015年预备党员自我评价
2015/03/04 职场文书
签证工作证明模板
2015/06/15 职场文书
浅谈MySQL之select优化方案
2021/08/07 MySQL
mysql中int(3)和int(10)的数值范围是否相同
2021/10/16 MySQL
使用Java去实现超市会员管理系统
2022/03/18 Java/Android