replace 替换全部的正确姿势
本文同步自我的个人博客: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 替换全部的正确姿势的更多相关文章
- JS中replace替换全部的正确应用
一般使用 var str = "test-test-test"; str = "test-test-test".replace("test" ...
- 判断是否为gif/png图片的正确姿势
判断是否为gif/png图片的正确姿势 1.在能取到图片后缀的前提下 1 2 3 4 5 6 7 8 9 //假设这是一个网络获取的URL NSString *path = @"http:/ ...
- 在Linux(ubuntu server)上面安装NodeJS的正确姿势
上一篇文章,我介绍了 在Windows中安装NodeJS的正确姿势,这一篇,我们继续来看一下在Linux上面安装和配置NodeJS. 为了保持一致,这里也列举三个方法 第一个方法:通过官网下载安装 h ...
- replace替换语句
t_sql语句:replace替换语句:update 表名 set 列名=REPLACE(列名,'替换的数据','替换后的数据')
- 【SQLite】使用replace替换字段中的字符
使用replace替换字段中的字符 如:替换production表中的specification字段中的两个空格为一个空格: update production set specification = ...
- 关于js的replace替换
关于js的replace替换 msgContent = msgContent.replace("a","b"); 这样的替换只会把第一个a替换成b,不会替换全部 ...
- 程序员取悦女朋友的正确姿势---Tips(iOS美容篇)
前言 女孩子都喜欢用美图工具进行图片美容,近来无事时,特意为某人写了个自定义图片滤镜生成器,安装到手机即可完成自定义滤镜渲染照片.app独一无二,虽简亦繁. JH定律:魔镜:最漂亮的女人是你老婆魔镜: ...
- JAVA insert() 插入字符串 reverse() 颠倒 delete()和deleteCharAt() 删除字符 replace() 替换 substring() 截取子串
insert() 插入字符串 StringBuffer insert(int index,String str) StringBuffer insert(int index,char ch) Stri ...
- ios监听ScrollView/TableView滚动的正确姿势
主要介绍 监测tableView垂直滚动的舒畅姿势 监测scrollView/collectionView横向滚动的正确姿势 1.监测tableView垂直滚动的舒畅姿势 通常我们用KVO或者在scr ...
随机推荐
- Effective Java 64 Strive for failure atomicity
Principle Failure atomic - A failed method invocation should leave the object in the state that it w ...
- Effective Java 70 Document thread safety
Principle The presence of the synchronized modifier in a method declaration is an implementation det ...
- HTTPS连接的前几毫秒发生了什么——Amazon HTTPS案例分析
转自: http://blog.jobbole.com/48369/ 提示:英文原文写于2009年,当时的Firefox和最新版的Firefox,界面也有很大改动.以下是正文. 花了数小时阅读了如潮的 ...
- Java内存模型的历史变迁
转自:http://www.csdn.net/article/2015-05-20/2824722-Java 摘要:本文通过介绍Java的新/旧内存模型,来展示Java技术的历史变迁. 本文通过介绍J ...
- c# 反射简单使用
类库dll,将生成ExampleLib.dll文件 namespace ExampleLib { public class Example { public static string FuncA() ...
- HTML5 自定义属性 data-* 和 jQuery.data 详解
新的HTML5标准允许你在普通的元素标签里,嵌入类似data-*的属性,来实现一些简单数据的存取.它的数量不受限制,并且也能由javascript动态修改,也支持CSS选择器进行样式设置.这使得dat ...
- javascript图片库
将图片发布到网上的办法很多,可以简单地把所有图片都放在一个网页中,但是会导致这个网页过于庞大.为每张图片分别创建一个网页的解决办法值得考虑,但是制作过程需要花费非常多的时间和精力. 如果想要两全其美, ...
- PowerDesigner概述(系统分析与建模)以及如何用PowerDesigner快速的创建出这个数据库
PowerDesigner是Sybase公司推出的一个集成了企业架构,UML(统一建模语言)和数据库的CASE(计算机辅助软件工程)工具.它 不仅可以用于系统设计和开发的不同阶段(即业务分析,概念模型 ...
- Ubuntu 14.04 LTS Server 无法挂载光盘 启动initramfs等问题
今天需要在戴尔R410服务器上装64位的Linux,师兄给了个14.04的server 64位镜像.一开始打算用U盘安装,用软碟通烧写镜像之后,在服务器端设置从U盘启动,但是安装到一半出现了光盘无法挂 ...
- "德意志之歌"的历史
1841年8月, 词作家奥古斯特在当时属于英国的黑尔格兰岛上度假时, 创作了"德意志之歌"的歌词.9月, 这首歌首次出版发行, 曲调则借用了海顿的一首君主颂歌 - "皇帝 ...