如何在JavaScript中replace所有出现的string?
我有这个string:
"Test abc test test abc test test test abc test test abc"
干
str = str.replace('abc', '');
似乎只能删除上面string中第一次出现的abc
。 我怎样才能取代所有的事件呢?
为了完整起见,我想到了用什么方法来做到这一点。 基本上有两种方法可以按照本页其他答案的build议进行操作。
注意:通常,不推荐使用JavaScript扩展内置的原型。 为了说明的目的,我在String原型上作为扩展提供,在String
内置原型上显示了假设标准方法的不同实现。
正则expression式的实现
String.prototype.replaceAll = function(search, replacement) { var target = this; return target.replace(new RegExp(search, 'g'), replacement); };
拆分和join(function)实现
String.prototype.replaceAll = function(search, replacement) { var target = this; return target.split(search).join(replacement); };
我不太了解正则expression式在效率方面如何在幕后工作,我往往倾向于分裂,在过去没有考虑性能的情况下参与实施。 当我想知道哪个更有效率,以什么边际,我用它作为找借口。
在我的Chrome Windows 8机器上, 基于正则expression式的实现速度最快 , 分离和连接实现速度降低了53% 。 这意味着正则expression式是我使用的lorem ipsuminput的两倍。
看看这个基准运行这两个实现对彼此。
正如@ThomasLeduc和其他人在下面的评论中指出的那样,如果search
包含某些在正则expression式中保留为特殊字符的字符,那么基于正则expression式的实现可能会出现问题。 该实现假定调用者将事先转义string,或者只传递在正则expression式 (MDN)中的表中没有字符的string。
MDN也提供了一个实现来逃避我们的string。 这将是很好,如果这也是RegExp.escape(str)
,但唉,它不存在:
function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string }
我们可以在我们的String.prototype.replaceAll
实现中调用escapeRegExp
,但是,我不确定这会影响性能(甚至对于不需要转义的string,如所有字母数字string)。
str = str.replace(/abc/g, '');
回应评论:
var find = 'abc'; var re = new RegExp(find, 'g'); str = str.replace(re, '');
为了回应Click Upvote的评论,你可以更简化它:
function replaceAll(str, find, replace) { return str.replace(new RegExp(find, 'g'), replace); }
注意:正则expression式包含特殊(meta)字符,因此在上面的find
函数中盲目地传递一个参数而不预先处理它来转义这些字符是危险的。 这在Mozilla开发者networking的正则expression式的JavaScript指南中有介绍 ,它们提供了以下的实用function:
function escapeRegExp(str) { return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); }
因此,为了使上面的replaceAll()
函数更安全,如果还包含escapeRegExp
,可以将其修改为以下escapeRegExp
:
function replaceAll(str, find, replace) { return str.replace(new RegExp(escapeRegExp(find), 'g'), replace); }
注意:不要在真实的代码中使用它。
作为一个简单的文字string的正则expression式的替代,你可以使用
str = "Test abc test test abc test...".split("abc").join("");
一般模式是
str.split(search).join(replacement)
在使用replaceAll
和一个正则expression式的情况下,这样做的速度会更快,但在现代浏览器中似乎不再是这种情况。 所以,这实际上只能作为一个快速入侵,以避免需要逃避正则expression式,而不是真正的代码。
使用g
标志设置的正则expression式将取代所有:
someString = 'the cat looks like a cat'; anotherString = someString.replace(/cat/g, 'dog'); // anotherString now contains "the dog looks like a dog"
也看到这里
这是一个基于公认的答案的string原型函数:
String.prototype.replaceAll = function (find, replace) { var str = this; return str.replace(new RegExp(find, 'g'), replace); };
编辑
如果你的find
将包含特殊字符,那么你需要逃避它们:
String.prototype.replaceAll = function (find, replace) { var str = this; return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace); };
小提琴: http : //jsfiddle.net/cdbzL/
更新:
更新有些晚了,但是因为我偶然发现了这个问题,并且注意到我之前的回答并不是我所满意的。 由于问题涉及replace一个单词,这是令人难以置信的,没有人想到使用单词边界( \b
)
'a cat is not a caterpillar'.replace(/\bcat\b/gi,'dog'); //"a dog is not a caterpillar"
这是一个简单的正则expression式,避免在大多数情况下replace单词的部分。 然而,短划线-
仍然被认为是一个字的边界。 所以在这种情况下可以使用条件来避免replace像cool-cat
这样的string:
'a cat is not a cool-cat'.replace(/\bcat\b/gi,'dog');//wrong //"a dog is not a cool-dog" -- nips 'a cat is not a cool-cat'.replace(/(?:\b([^-]))cat(?:\b([^-]))/gi,'$1dog$2'); //"a dog is not a cool-cat"
基本上,这个问题和这里的问题是一样的: Javascript用“”replace“”“
@迈克,检查我给了那里的答案…正则expression式是不是唯一的方法来取代多次出现,子离子,远离它。 灵活思考,思考分裂!
var newText = "the cat looks like a cat".split('cat').join('dog');
或者,为了防止replace字的部分,也就是批准的答案。 你可以用正则expression式来解决这个问题,我承认,这个expression式有点复杂,作为一个结果,稍微慢一些:
var regText = "the cat looks like a cat".replace(/(?:(^|[^az]))(([^az]*)(?=cat)cat)(?![az])/gi,"$1dog");
输出与接受的答案相同,但是,在此string上使用/ cat / gexpression式:
var oops = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/cat/g,'dog'); //returns "the dog looks like a dog, not a dogerpillar or cooldog" ??
糟糕,这可能不是你想要的。 那么是什么? 恕我直言,只是有条件地取代'猫'的正则expression式。 (即不是一个单词的一部分),如下所示:
var caterpillar = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/(?:(^|[^az]))(([^az]*)(?=cat)cat)(?![az])/gi,"$1dog"); //return "the dog looks like a dog, not a caterpillar or coolcat"
我的猜测是,这符合你的需求。 当然,这不是全面的,但它应该足以让你开始。 我build议阅读更多的这些网页。 这将有助于完善这个expression式来满足您的特定需求。
http://www.javascriptkit.com/jsref/regexp.shtml
http://www.regular-expressions.info
最后join:
鉴于这个问题仍然有很多观点,我想我可能会添加一个.replace
用于callback函数的例子。 在这种情况下,它极大地简化了expression式, 并提供了更大的灵活性,例如用正确的大小写replace或一次性replacecat
和cats
:
'Two cats are not 1 Cat! They\'re just cool-cats, you caterpillar' .replace(/(^|.\b)(cat)(s?\b.|$)/gi,function(all,char1,cat,char2) { //check 1st, capitalize if required var replacement = (cat.charAt(0) === 'C' ? 'D' : 'd') + 'og'; if (char1 === ' ' && char2 === 's') {//replace plurals, too cat = replacement + 's'; } else {//do not replace if dashes are matched cat = char1 === '-' || char2 === '-' ? cat : replacement; } return char1 + cat + char2;//return replacement string }); //returns: //Two dogs are not 1 Dog! They're just cool-cats, you caterpillar
与全球正则expression式匹配:
anotherString = someString.replace(/cat/g, 'dog');
str = str.replace(/abc/g, '');
或者从这里尝试replaceAll函数:
什么是扩展内置对象的有用的JavaScript方法?
str = str.replaceAll('abc', ''); OR var search = 'abc'; str = str.replaceAll(search, '');
编辑:澄清关于replaceAll可用性
'replaceAll'方法被添加到String的原型。 这意味着它将可用于所有string对象/文字。
例如
var output = "test this".replaceAll('this', 'that'); //output is 'test that'. output = output.replaceAll('that', 'this'); //output is 'test this'
使用正则expression式:
str.replace(/abc/g, '');
这是不使用正则expression式的最快版本。
修正了jsperf
replaceAll = function(string, omit, place, prevstring) { if (prevstring && string === prevstring) return string; prevstring = string.replace(omit, place); return replaceAll(prevstring, omit, place, string) }
它几乎是分割和连接方法的两倍 。
正如在这里的评论中指出的那样,如果你的omit
variables包含place
,那么这将不起作用,如: replaceAll("string", "s", "ss")
,因为它总是能够replace另一个字。
还有另一个与我的recursionreplacejsperf变得更快( http://jsperf.com/replace-all-vs-split-join/12 )!
- 2017年7月27日更新:看起来RegExp现在在最近发布的Chrome 59中performance最快。
假设你想用'x'代替所有'abc':
let some_str = 'abc def def lom abc abc def'.split('abc').join('x') console.log(some_str) //x def def lom xx def
我试图想想比修改string原型更简单的事情。
//循环,直到数字出现为0或者只是复制/粘贴
function replaceAll(find, replace, str) { while( str.indexOf(find) > -1) { str = str.replace(find, replace); } return str; }
简单…
replace单引号:
function JavaScriptEncode(text){ text = text.replace(/'/g,''') // More encode here if required return text; }
function replaceAll(str, find, replace) { var i = str.indexOf(find); if (i > -1){ str = str.replace(find, replace); i = i + replace.length; var st2 = str.substring(i); if(st2.indexOf(find) > -1){ str = str.substring(0,i) + replaceAll(st2, find, replace); } } return str; }
var str = "ff ff ffa de def"; str = str.replace(/f/g,''); alert(str);
如果你想find的东西已经在一个string中,而且你没有一个正则expression式,你可以使用join / split:
function replaceMulti(haystack, needle, replacement) { return haystack.split(needle).join(replacement); } someString = 'the cat looks like a cat'; anotherString = replaceMulti(someString, 'cat', 'dog');
我喜欢这个方法(看上去有点干净):
text = text.replace(new RegExp("cat","g"), "dog");
while (str.indexOf('abc') !== -1) { str = str.replace('abc', ''); }
如果您正在尝试确保即使在更换后您所查找的string也不存在,则需要使用循环。
例如:
var str = 'test aabcbc'; str = str.replace(/abc/g, '');
完成后,您仍然可以“testingabc”!
解决这个问题的最简单的循环是:
var str = 'test aabcbc'; while (str != str.replace(/abc/g, '')){ str.replace(/abc/g, ''); }
但是,每个周期运行两次更换。 也许(可能被拒绝)可以组合成一个稍微更高效但不太可读的forms:
var str = 'test aabcbc'; while (str != (str = str.replace(/abc/g, ''))){} // alert(str); alerts 'test '!
这在查找重复的string时特别有用。
例如,如果我们有'a ,,, b',我们希望删除所有重复的逗号。
[在这种情况下,可以使用.replace(/,+ / g,','),但是在某个时候,正则expression式变得复杂而且慢得足以循环。]
你可以简单地使用下面的方法
/** * Replace all the occerencess of $find by $replace in $originalString * @param {originalString} input - Raw string. * @param {find} input - Target key word or regex that need to be replaced. * @param {replace} input - Replacement key word * @return {String} Output string */ function replaceAll(originalString, find, replace) { return originalString.replace(new RegExp(find, 'g'), replace); };
虽然人们已经提到了正则expression式的使用,但是如果要replace文本而不考虑文本的情况,还有更好的方法。 像大写或小写。 使用下面的语法
//Consider below example originalString.replace(/stringToBeReplaced/gi, ''); //Output will be all the occurrences removed irrespective of casing.
你可以参考这里的详细例子。
只需添加/g
document.body.innerHTML = document.body.innerHTML.replace('hello', 'hi');
至
// Replace 'hello' string with /hello/g regular expression. document.body.innerHTML = document.body.innerHTML.replace(/hello/g, 'hi');
/g
意味着全球
以下function适用于我:
String.prototype.replaceAllOccurence = function(str1, str2, ignore) { return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2); } ;
现在调用这样的函数:
"you could be a Project Manager someday, if you work like this.".replaceAllOccurence ("you", "I");
只需将此代码复制并粘贴到浏览器控制台中即可。
我的实现,非常自我解释
function replaceAll(string, token, newtoken) { if(token!=newtoken) while(string.indexOf(token) > -1) { string = string.replace(token, newtoken); } return string; }
我使用p来存储以前的recursionreplace的结果:
function replaceAll(s, m, r, p) { return s === p || r.contains(m) ? s : replaceAll(s.replace(m, r), m, r, s); }
它将replacestrings中的所有事件,直到可能:
replaceAll('abbbbb', 'ab', 'a') → 'abbbb' → 'abbb' → 'abb' → 'ab' → 'a'
为了避免无限循环,我检查replacer是否包含匹配m :
replaceAll('abbbbb', 'a', 'ab') → 'abbbbb'
大多数人可能会这样做的URL编码。 要对URL进行编码,您不仅应该考虑空格,还应该使用encodeURI
正确地转换整个string。
encodeURI("http://www.google.com/a file with spaces.html")
要得到:
http://www.google.com/a%20file%20with%20spaces.html
如果string包含像abccc类似的模式使用使用:
str.replace(/abc(\s|$)/g,"")
为了replace所有types的字符,请尝试下面的代码:
Suppose we have need to send " and \ in my string, then we will convert it " to \" and \ to \\
所以这个方法将解决这个问题。
String.prototype.replaceAll = function (find, replace) { var str = this; return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace); }; var message = $('#message').val(); message = message.replaceAll('\\', '\\\\'); /*it will replace \ to \\ */ message = message.replaceAll('"', '\\"'); /*it will replace " to \\"*/
我使用的是Ajax,而且我需要以JSON格式发送参数。 那么我的方法是这样的:
function sendMessage(source, messageID, toProfileID, userProfileID) { if (validateTextBox()) { var message = $('#message').val(); message = message.replaceAll('\\', '\\\\'); message = message.replaceAll('"', '\\"'); $.ajax({ type: "POST", async: "false", contentType: "application/json; charset=utf-8", url: "services/WebService1.asmx/SendMessage", data: '{"source":"' + source + '","messageID":"' + messageID + '","toProfileID":"' + toProfileID + '","userProfileID":"' + userProfileID + '","message":"' + message + '"}', dataType: "json", success: function (data) { loadMessageAfterSend(toProfileID, userProfileID); $("#<%=PanelMessageDelete.ClientID%>").hide(); $("#message").val(""); $("#delMessageContainer").show(); $("#msgPanel").show(); }, error: function (result) { alert("message sending failed"); } }); } else { alert("Please type message in message box."); $("#message").focus(); } } String.prototype.replaceAll = function (find, replace) { var str = this; return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace); };
如果使用库是您的一个select,那么您将获得与库函数一起使用的testing和社区支持的好处。 例如, string.js库有一个replaceAll()函数,它可以完成你正在寻找的任务:
// Include a reference to the string.js library and call it (for example) S. str = S(str).replaceAll('abc', '').s;
function replaceAll(str, find, replace) { var $r=""; while($r!=str){ $r = str; str = str.replace(find, replace); } return str; }