本文同步自我的个人博客:http://www.52cik.com/2015/11/06/replace-all.html

关于字符串替换问题,其实是个很简单的问题,但却也不那么简单,至少对于很多新手而言,全局替换一直是个坑。

简单而强大的正则

可能你觉得要替换全局,就改成正则,然后加个 g 全局匹配就好了,例如:

var str = "test-test-test";
str = "test-test-test".replace("test", "ok");
console.log(str);

改成正则:

var str = "test-test-test";
str = "test-test-test".replace(/test/g, "ok");
console.log(str);

确实非常简单,但是如果出现需要转义的字符呢?

当然也难不倒大家,但是对于新手而言,正则就是一座无形的大山,完全无法越过。

无奈的正则

例如表情标签的替换呢?难道全部改成正则?那也要会正则的人花不少体力才能搞定吧。

今天群里的朋友就遇到这么个问题,表情标签如下:

var faces = {
"/::)": "weixiao",
"/::~": "pizui",
"/::B": "se",
"/::|": "fadai",
"/:8-)": "deyi",
"/::<":"liulei",
"/::$": "haixiu",
"/::'(": "daku",
"/::-|": "gangga"
};

当然我只是截取了部分,好像有好几十个,如果全部改成正则,需要不少体力呢。

循环替换

这种情况,我们需要正常的字符串替换,例如结合 while + indexOf 实现。

var faces = {
"/::)": "weixiao",
"/::~": "pizui",
"/::B": "se",
"/::|": "fadai",
"/:8-)": "deyi",
"/::<":"liulei",
"/::$": "haixiu",
"/::'(": "daku",
"/::-|": "gangga"
}; var str = "/::)-/::B-/::)-/:8-)-/:8-)"; for (var k in faces) {
while(str.indexOf(k) > -1) {
str = str.replace(k, faces[k]);
}
} console.log(str);

这样,基本功能实现,不过这是有问题的,如果有一个键值相同的,就会死循环例如:

var faces = {
"/::)": "weixiao",
"/:hehe": "/:hehe"
}; var str = "/::)-/::B-/:hehe-/:8-)-/:8-)"; for (var k in faces) {
while(str.indexOf(k) > -1) {
str = str.replace(k, faces[k]);
}
} console.log(str);

这样,就呵呵了,当然不一定会有这样的情况,但也不能肯定一定没有这样的情况。

改进循环

我们需要用到 indexOf 的第二个参数来规避这种情况,改进后的代码如下:

var faces = {
"/::)": "weixiao",
"/:hehe": "/:hehe"
}; var str = "/::)-/::B-/:hehe-/:8-)-/:8-)"; for (var k in faces) {
var p = -1; // 字符出现位置
var s = 0; // 下一次起始位置
while((p = str.indexOf(k, s)) > -1) {
s = p + faces[k].length; // 位置 + 值的长度
str = str.replace(k, faces[k]);
}
} console.log(str);

好了,现在这样就没问题了,也不用担心死循环问题,而且替换大段文字的时候,性能比正则要好。 经过测试,确实正则快。

在大段正则匹配的时候,回溯会导致匹配性能问题,所以才一直认为正则慢,而这种情况的正则,不需要回溯,性能自然也极佳。

为了方便新手朋友使用,下面写个函数吧。

/**
* 字符串替换
* @param {string} str 要被替换的字符串
* @param {string} substr 要替换的字符串
* @param {string} newstr 用于替换的字符串
* @return {string} 替换后的新字符串
*/
function replace(str, substr, newstr) {
var p = -1; // 字符出现位置
var s = 0; // 下一次起始位置 while((p = str.indexOf(substr, s)) > -1) {
s = p + newstr.length; // 位置 + 值的长度
str = str.replace(substr, newstr);
} return str;
} console.log( replace("ssssss", "ss", "s") ); // sss

总结

我发现,我也只能写写这些小东西,唉。。

后记

在 4楼 Antineutrino 的测试中得知,正则方法比 while + indexOf 性能更佳。

之前一直认为正则就是慢的代名词,所以直接忽略了正则方法,现在又重新认识了正则,正则果然犀利。

抽空写了个正则版本的,把元字符种的几个符号转义下,就可以生成正则了。

网上那些正则版本中没有转义直接 new RegExp 的会导致各种bug,所以要处理下元字符的那些符号。

/**
* 字符串替换
* @param {string} str 要被替换的字符串
* @param {string} substr 要替换的字符串
* @param {string} newstr 用于替换的字符串
* @return {string} 替换后的新字符串
*/
function replace(str, substr, newstr) {
substr = substr.replace(/[.\\[\]{}()|^$?*+]/g, "\\$&"); // 转义字符串中的元字符
var re = new RegExp(substr, "g"); // 生成正则
return str.replace(re, newstr);
} console.log( replace("ssssss", "ss", "s") ); // sss

replace 替换全部的正确姿势的更多相关文章

  1. JS中replace替换全部的正确应用

    一般使用 var str = "test-test-test"; str = "test-test-test".replace("test" ...

  2. 判断是否为gif/png图片的正确姿势

    判断是否为gif/png图片的正确姿势 1.在能取到图片后缀的前提下 1 2 3 4 5 6 7 8 9 //假设这是一个网络获取的URL NSString *path = @"http:/ ...

  3. 在Linux(ubuntu server)上面安装NodeJS的正确姿势

    上一篇文章,我介绍了 在Windows中安装NodeJS的正确姿势,这一篇,我们继续来看一下在Linux上面安装和配置NodeJS. 为了保持一致,这里也列举三个方法 第一个方法:通过官网下载安装 h ...

  4. replace替换语句

    t_sql语句:replace替换语句:update 表名 set 列名=REPLACE(列名,'替换的数据','替换后的数据')

  5. 【SQLite】使用replace替换字段中的字符

    使用replace替换字段中的字符 如:替换production表中的specification字段中的两个空格为一个空格: update production set specification = ...

  6. 关于js的replace替换

    关于js的replace替换 msgContent = msgContent.replace("a","b"); 这样的替换只会把第一个a替换成b,不会替换全部 ...

  7. 程序员取悦女朋友的正确姿势---Tips(iOS美容篇)

    前言 女孩子都喜欢用美图工具进行图片美容,近来无事时,特意为某人写了个自定义图片滤镜生成器,安装到手机即可完成自定义滤镜渲染照片.app独一无二,虽简亦繁. JH定律:魔镜:最漂亮的女人是你老婆魔镜: ...

  8. JAVA insert() 插入字符串 reverse() 颠倒 delete()和deleteCharAt() 删除字符 replace() 替换 substring() 截取子串

    insert() 插入字符串 StringBuffer insert(int index,String str) StringBuffer insert(int index,char ch) Stri ...

  9. ios监听ScrollView/TableView滚动的正确姿势

    主要介绍 监测tableView垂直滚动的舒畅姿势 监测scrollView/collectionView横向滚动的正确姿势 1.监测tableView垂直滚动的舒畅姿势 通常我们用KVO或者在scr ...

随机推荐

  1. java web中日期Date类型在页面中格式化显示的三种方式

    一般我们经常需要在将服务器端的Date类型,传到页面进行显示,这就涉及到一个如何格式化显示Date类型的问题,一般我们有三种方式进行: 1)在服务端使用SimpleDateFormat等类格式化成字符 ...

  2. WebAPP与原生APP的交互设计区别

    WebAPP和原生APP同为移动端,很少有研究这两项的交互区别,最近公司做了一次从原生APP到WebAPP(HTML5 )的移植,故总结一下期间遇到的问题及不同点总结. 从使用场景上,WebAPP用户 ...

  3. jQuery Form 表单提交插件-----formSerialize,fieldSerialize,fieldValue,resetForm,clearForm,clearFields的 应用

    一.jQuery Form的其他api  1.  formSerialize 将表单序列化成查询串.这个方法将返回一个形如: name1=value1&name2=value2的字符串.是否可 ...

  4. 一个不错的shell 脚本教程 入门级

    一个很不错的bash脚本编写教程,至少没接触过BASH的也能看懂     建立一个脚本 Linux中有好多中不同的shell,但是通常我们使用bash (bourne again shell) 进行s ...

  5. 重载 && 重载递增递和减运算符

    class Rule { private: double m_Length; public: explicit Rule(double lg = 1.0) :m_Length{ lg }{} Rule ...

  6. find type d 命令批量删除禁用

    [root@qike ~]# find  /usr/local/sbin/  -type d  /usr/local/sbin//usr/local/sbin/2/usr/local/sbin/g/u ...

  7. opencv3.1 + opencv_contrib编译记事(win7下)

    折腾了好几天,终于把opencv3.1加上一个额外的包opencv_contrib编译好了.(总体来说编译opencv就是填坑!!!) 最后我编译成功的是mingw版本的.也就是结合了Qt4.7+cm ...

  8. Genymotion出现unknown generic error和This may occur if you are using a proxy错误的解决方案

    今天在实验室希望在Genymotion上多下载几个模拟器,需要重新登录帐号,却发现一个错误,叫做unknown generic error.前几天还出现过一个很诡异的问题.截图如下: . (1)unk ...

  9. Volley(四)—— ImageLoader & NetworkImageView

    Volley(四)—— ImageLoader & NetworkImageView ImageLoader是一个加载网络图片的封装类,其内部还是由ImageRequest来实现的.但因为源码 ...

  10. iOS app上传错误集锦(转载)

    1.工程里增加了版本自动更新. 2.未增加判断网络状态的类Reachability. 3.问题:error itms -90049 This bundel is invalid. The bundle ...