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

轉載于:https://www.cnblogs.com/52cik/p/replace-all.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375405.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375405.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375405.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JAVA - 單例設計模式

JAVA - 單例設計模式 一. 簡介二. 單例模式的原則三. 單例模式的實現1.1 餓漢式1.1.1 靜態變量初始化方式1.1.2 靜態代碼塊初始化方式1.1.3 枚舉方式 1.2 懶漢式1.2.1 懶加載初始化方法 (線程不安全)1.2.2 懶加載初始化方法 (線程安全&#x…

http請求報文

關于urlURL 是大型標識符 URI(統一資源標識)的一部分。這個超集是建立在已有的命名慣例基礎上的。一個 URL 是一個簡單的 URI,使用已存在的協議或規劃(也就是 http,ftp 等)作為地址的一部分。為了進一步描繪這些,我們將會Edit By Vheavens Edit By Vheavens 引入 non-URL 的 UR…

operanbsp;內容攔截

結束我大opera的一個好用功能 內容攔截 博客的主要很清爽,也可以自定義.非常好, 但打開博文,左邊的特別的精彩圖文,瞄到就不高興.好的 開始 右鍵-內容攔截 shift 點那個精彩xx,最右上角,廣告, 然后點完成.ok了 貌似我大遨游的廣告攔截更好用 轉載于:https://www.cnblogs.com/wa…

Solr-5.3.1安裝配置

Solr-5.3.1安裝配置官方網站:http://lucene.apache.org/solr/http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htmlhttp://lucene.apache.org/solr/quickstart.html環境:CentOS6 x64Solr-5.3.1從Solr5.0開始,Solr不再發布為在任何…

EF for Firebird

今天用了Firebird,記錄下怎么用,不然下次給忘記了 1.官網下載包 1.DDEXProvider-3.0.1.0.msi 2.FirebirdSql.Data.FirebirdClient-4.6.2.0.msi 備注: 1.發現DDEXProvider 與 FirebirdSql.Data.FirebirdClient安裝有先后順序 1.如果中間出現了…

php幾個函數

1. dirname (PHP 3, PHP 4, PHP 5) dirname -- 返回路徑中的目錄部分說明 string dirname ( string path )給出一個包含有指向一個文件的全路徑的字符串,本函數返回去掉文件名后的目錄名。 在 Windows 中,斜線(/)和反斜線&#xf…

Struts2 自定義攔截器(easy example)

要自定義攔截器需要實現com.opensymphony.xwork2.interceptor.Interceptor接口: 新建一個MyInterceptpackage com.action;import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor;public class MyInterceptor i…

img標簽在div里上下居中

方法一&#xff1a;圖片尺寸未知&#xff0c;IE8-不支持 CSS部分&#xff1a; <style> .content{width:500px;height:500px;border:1px solid black;position:relative; } </style>DOM部分&#xff1a; <div class"content"> <img src"htt…

(接口)銀聯證書上傳被修改的問題和讀取證書的絕對路徑問題

最近在做對接銀聯的支付接口。相對于支付寶、微信支付&#xff0c;銀聯支付接口應該是做的最完美的了。銀聯支付平臺提供了足夠詳細的接口文檔&#xff0c;接口demo&#xff0c;常見問題解決方案。 更人性化的是&#xff0c;個人可以免費注冊一個商家賬號&#xff0c;提供給你免…

控制器對視圖聲明周期的控制

init&#xff0d;初始化程序 viewDidLoad&#xff0d;加載視圖 viewWillAppear&#xff0d;UIViewController對象的視圖即將加入窗口時調用&#xff1b; viewDidApper&#xff0d;UIViewController對象的視圖已經加入到窗口時調用&#xff1b; viewWillDisappear&#xff0d;UI…

MST:Bad Cowtractors(POJ 2377)

壞的牛圈建筑 題目大意&#xff1a;就是現在農夫又要牛修建牛欄了&#xff0c;但是農夫想不給錢&#xff0c;于是牛就想設計一個最大的花費的牛圈給他&#xff0c;牛圈的修理費用主要是用在連接牛圈上 這一題很簡單了&#xff0c;就是找最大生成樹&#xff0c;把Kruskal算法改一…

有關進程的一些基本概念

對進程的初步描述 一.和進程有關的一些概念 ①一個進程就是一個正在執行程序的實例&#xff0c;包括程序計數器&#xff0c;寄存器和變量的當前值。 從概念上說&#xff0c;每個進程擁有它自己的虛擬CPU&#xff0c;當然真實的CPU在各個進程之間來回切換。 ②在某一瞬間&…

第4章 maven依賴特性

第4章 maven依賴特性 本章詳細介紹maven的依賴特性和依賴范圍&#xff0c;如何排除依賴。 4.1 什么是依賴傳遞 舉個例子 在非maven項目中&#xff0c;你需要使用spring功能&#xff0c;你會想到導入spring的jar包&#xff0c;那么&#xff0c;srping又需要其他依賴jar包支持&a…

lintcode :Integer to Roman 整數轉羅馬數字

題目 整數轉羅馬數字 給定一個整數&#xff0c;將其轉換成羅馬數字。 返回的結果要求在1-3999的范圍內。 樣例 4 -> IV 12 -> XII 21 -> XXI 99 -> XCIX 更多案例&#xff0c;請戳 http://literacy.kent.edu/Minigrants/Cinci/romanchart.htm 說明 什么是 羅馬數字…

Win32ASm學習[1]:RadASm下測試Debug

okay 正文開始下面的代碼如果不能編譯 請把你的RadAsm下的Masm32這個文件夾復制到任意一個磁盤的根目錄下&#xff0c;在進行編譯就可以了 或者安裝Masm32 SDK到任意磁盤根目錄下 .386.model flat,stdcalloption casemap:none;>>>>>>>>>>&g…

關于javascript閉包

1.閉包的概念 閉包就是能夠讀取其他函數內部變量的函數。 由于在Javascript語言中&#xff0c;只有函數內部的子函數才能讀取局部變量&#xff0c;因此可以把閉包簡單理解成“定義在一個函數內部的函數”。 所以&#xff0c;在本質上&#xff0c;閉包就是將函數內部和函數外部連…

Win32ASM學習[2]:運算符

算術運算符 名稱 優先級 () 圓括號 1 ,- 正、負 2 *,/ 乘、除 3 MOD 取模 3 ,- 加、減 4 ------------------------------------------------------------------------------------------------------------------------------------------ .386 .mo…

正式入住了

從13年開始從事iOS開發工作,就準備寫一些東西,記錄這一路學習工作之旅,但是總是想著堅持不下來,也就慢慢的放棄了,開始用一些記筆記的軟件,印象筆記用過,個人體驗比較差,后來又用了OneNote,這個APP還是比較舒服,但是由于公司的老版mac-pro,無法使用,也就突然想起了,也是時候重出…

VRRP協議具體解釋

轉帖&#xff1a;http://blog.chinaunix.net/space.php?uid11654074&doblog&id2857384 Contents Page 文件夾 入木三分學網絡…