ChatGPT解决这个技术问题 Extra ChatGPT

How to replace all occurrences of a string in JavaScript

I have this string in my JavaScript code:

"Test abc test test abc test test test abc test test abc"

Doing:

str = str.replace('abc', '');

Seems to only remove the first occurrence of abc in the string above.

How can I replace all occurrences of it?

When replacing all occurrences of aba in ababa with ca, which result do you expect? caba? abca? cca?
String.prototype.replaceAll() is now a standard part of ECMAScript tc39.es/ecma262/#sec-string.prototype.replaceall, documented at developer.mozilla.org/docs/Web/JavaScript/Reference/… and shipped in Safari 13.1, Firefox 77 and Chrome Dev/Canary and will ship in Chrome 85. From the docs: “If searchValue is a string, replaces all occurrences of searchValue (as if .split(searchValue).join(replaceValue) or a global & properly-escaped regular expression had been used). If searchValue is a non-global regular expression, throws an exception”
Use regex instead of string, should look like str.replace(/abc/g, ''); so g to get all matches.

i
izogfif

As of August 2020: Modern browsers have support for the String.replaceAll() method defined by the ECMAScript 2021 language specification.

For older/legacy browsers:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

Here is how this answer evolved:

str = str.replace(/abc/g, '');

In response to comment "what's if 'abc' is passed as a variable?":

var find = 'abc';
var re = new RegExp(find, 'g');

str = str.replace(re, '');

In response to Click Upvote's comment, you could simplify it even more:

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(find, 'g'), replace);
}

Note: Regular expressions contain special (meta) characters, and as such it is dangerous to blindly pass an argument in the find function above without pre-processing it to escape those characters. This is covered in the Mozilla Developer Network's JavaScript Guide on Regular Expressions, where they present the following utility function (which has changed at least twice since this answer was originally written, so make sure to check the MDN site for potential updates):

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

So in order to make the replaceAll() function above safer, it could be modified to the following if you also include escapeRegExp:

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

In escapeRegExp the ] and } are extra (not necessary to be escaped). It is better to be like: .replace(/[.^$*+?()[{|\\]/g, "\\$&")
You also need to escape the replacement string (consider how escapeRegExp uses $& in the replacement string for special behavior). Change last replace in last code block to replace.replace(/\$/g, '$$$$'). See stackoverflow.com/a/6969486/2730641 Test case: replaceAll('abc def abc', 'abc', '$&@%#!') // Censor 'abc'
P
Peter Mortensen

For the sake of completeness, I got to thinking about which method I should use to do this. There are basically two ways to do this as suggested by the other answers on this page.

Note: In general, extending the built-in prototypes in JavaScript is generally not recommended. I am providing as extensions on the String prototype simply for purposes of illustration, showing different implementations of a hypothetical standard method on the String built-in prototype.

Regular Expression Based Implementation

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

Split and Join (Functional) Implementation

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

Not knowing too much about how regular expressions work behind the scenes in terms of efficiency, I tended to lean toward the split and join implementation in the past without thinking about performance. When I did wonder which was more efficient, and by what margin, I used it as an excuse to find out.

On my Chrome Windows 8 machine, the regular expression based implementation is the fastest, with the split and join implementation being 53% slower. Meaning the regular expressions are twice as fast for the lorem ipsum input I used.

Check out this benchmark running these two implementations against each other.

As noted in the comment below by @ThomasLeduc and others, there could be an issue with the regular expression-based implementation if search contains certain characters which are reserved as special characters in regular expressions. The implementation assumes that the caller will escape the string beforehand or will only pass strings that are without the characters in the table in Regular Expressions (MDN).

MDN also provides an implementation to escape our strings. It would be nice if this was also standardized as RegExp.escape(str), but alas, it does not exist:

function escapeRegExp(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}

We could call escapeRegExp within our String.prototype.replaceAll implementation, however, I'm not sure how much this will affect the performance (potentially even for strings for which the escape is not needed, like all alphanumeric strings).


In 2021 String.prototype.replaceAll() natively exist. So this implementation should be checked first before use.
m using nestjs, so typescript showing error that replaceAll is not method of String prototype, any solution for this?
M
Mario Petrovic

Update: In the latest versions of most popular browsers, you can use replaceAll as shown here:

let result = "1 abc 2 abc 3".replaceAll("abc", "xyz");
// `result` is "1 xyz 2 xyz 3"

But check Can I use or another compatibility table first to make sure the browsers you're targeting have added support for it first.

For Node and compatibility with older/non-current browsers:

Note: Don't use the following solution in performance critical code.

As an alternative to regular expressions for a simple literal string, you could use

str = "Test abc test test abc test...".split("abc").join("");

The general pattern is

str.split(search).join(replacement)

This used to be faster in some cases than using replaceAll and a regular expression, but that doesn't seem to be the case anymore in modern browsers.

Benchmark: https://jsben.ch/TZYzj

Conclusion:

If you have a performance critical use case (e.g processing hundreds of strings), use the Regexp method. But for most typical use cases, this is well worth not having to worry about special characters.


I discourage from using replaceAll at this moment (2020). It is not supported by some browsers that had updates in this year caniuse.com/?search=replaceAll It is too early
NodeJS supports replaceAll in 15.x versions.
what to do in case-sensitive case
The benchmark's plain replace function is not the equivalent of regex /g. "If pattern is a string, only the first occurrence will be replaced. " EX: replaceAll_0("foo bar foo") => "bar foo" when it should just be "bar". -MDN
M
Mario Petrovic

Using a regular expression with the g flag set will replace all:

someString = 'the cat looks like a cat';
anotherString = someString.replace(/cat/g, 'dog');
// anotherString now contains "the dog looks like a dog"

See here also


M
Mario Petrovic

Here's a string prototype function based on the accepted answer:

String.prototype.replaceAll = function (find, replace) {
    var str = this;
    return str.replace(new RegExp(find, 'g'), replace);
};

EDIT

If your find will contain special characters then you need to escape them:

String.prototype.replaceAll = function (find, replace) {
    var str = this;
    return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace);
};

Fiddle: http://jsfiddle.net/cdbzL/


M
Mario Petrovic

Update:

It's somewhat late for an update, but since I just stumbled on this question, and noticed that my previous answer is not one I'm happy with. Since the question involved replacing a single word, it's incredible nobody thought of using word boundaries (\b)

'a cat is not a caterpillar'.replace(/\bcat\b/gi,'dog');
//"a dog is not a caterpillar"

This is a simple regex that avoids replacing parts of words in most cases. However, a dash - is still considered a word boundary. So conditionals can be used in this case to avoid replacing strings like cool-cat:

'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"

Basically, this question is the same as the question here: Javascript replace " ' " with " '' "

@Mike, check the answer I gave there... regexp isn't the only way to replace multiple occurrences of a subsrting, far from it. Think flexible, think split!

var newText = "the cat looks like a cat".split('cat').join('dog');

Alternatively, to prevent replacing word parts -which the approved answer will do, too! You can get around this issue using regular expressions that are, I admit, somewhat more complex and as an upshot of that, a tad slower, too:

var regText = "the cat looks like a cat".replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");

The output is the same as the accepted answer, however, using the /cat/g expression on this string:

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" ?? 

Oops indeed, this probably isn't what you want. What is, then? IMHO, a regex that only replaces 'cat' conditionally. (ie not part of a word), like so:

var caterpillar = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");
//return "the dog looks like a dog, not a caterpillar or coolcat"

My guess is, this meets your needs. It's not fullproof, of course, but it should be enough to get you started. I'd recommend reading some more on these pages. This'll prove useful in perfecting this expression to meet your specific needs.

http://www.javascriptkit.com/jsref/regexp.shtml

http://www.regular-expressions.info

Final addition:

Given that this question still gets a lot of views, I thought I might add an example of .replace used with a callback function. In this case, it dramatically simplifies the expression and provides even more flexibility, like replacing with correct capitalisation or replacing both cat and cats in one go:

'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

M
Mario Petrovic

These are the most common and readable methods.

var str = "Test abc test test abc test test test abc test test abc"

Method 1:

str = str.replace(/abc/g, "replaced text");

Method 2:

str = str.split("abc").join("replaced text");

Method 3:

str = str.replace(new RegExp("abc", "g"), "replaced text");

Method 4:

while(str.includes("abc")){
   str = str.replace("abc", "replaced text");
}

Output:

console.log(str);
// Test replaced text test test replaced text test test test replaced text test test replaced text

s
scronide

Match against a global regular expression:

anotherString = someString.replace(/cat/g, 'dog');

M
Mihai Chelaru

For replacing a single time use:

var res = str.replace('abc', "");

For replacing multiple times use:

var res = str.replace(/abc/g, "");

n
nik7
str = str.replace(/abc/g, '');

Or try the replaceAll method, as recommended in this answer:

str = str.replaceAll('abc', '');

or:

var search = 'abc';
str = str.replaceAll(search, '');

EDIT: Clarification about replaceAll availability

The replaceAll method is added to String's prototype. This means it will be available for all string objects/literals.

Example:

var output = "test this".replaceAll('this', 'that'); // output is 'test that'.
output = output.replaceAll('that', 'this'); // output is 'test this'

A
Alireza

Using RegExp in JavaScript could do the job for you, just simply do something like below code, don't forget the /g after which standout for global:

var str ="Test abc test test abc test test test abc test test abc";
str = str.replace(/abc/g, '');

If you think of reuse, create a function to do that for you, but it's not recommended as it's only one line function, but again if you heavily use this, you can write something like this:

String.prototype.replaceAll = String.prototype.replaceAll || function(string, replaced) {
  return this.replace(new RegExp(string, 'g'), replaced);
};

and simply use it in your code over and over like below:

var str ="Test abc test test abc test test test abc test test abc";
str = str.replaceAll('abc', '');

But as I mention earlier, it won't make a huge difference in terms of lines to be written or performance, only caching the function may effect some faster performance on long strings and also a good practice of DRY code if you want to reuse.


P
Peter Mortensen

Say you want to replace all the 'abc' with 'x':

let some_str = 'abc def def lom abc abc def'.split('abc').join('x')
console.log(some_str) //x def def lom x x def

I was trying to think about something more simple than modifying the string prototype.


P
Peter Mortensen

Use a regular expression:

str.replace(/abc/g, '');

C
Community

Performance

Today 27.12.2019 I perform tests on macOS v10.13.6 (High Sierra) for the chosen solutions.

Conclusions

The str.replace(/abc/g, ''); (C) is a good cross-browser fast solution for all strings.

Solutions based on split-join (A,B) or replace (C,D) are fast

Solutions based on while (E,F,G,H) are slow - usually ~4 times slower for small strings and about ~3000 times (!) slower for long strings

The recurrence solutions (RA,RB) are slow and do not work for long strings

I also create my own solution. It looks like currently it is the shortest one which does the question job:

str.split`abc`.join``

str = "Test abc test test abc test test test abc test test abc"; str = str.split`abc`.join`` console.log(str);

Details

The tests were performed on Chrome 79.0, Safari 13.0.4 and Firefox 71.0 (64 bit). The tests RA and RB use recursion. Results

https://i.stack.imgur.com/si5UK.png

Short string - 55 characters

You can run tests on your machine HERE. Results for Chrome:

https://i.stack.imgur.com/Ctf18.png

Long string: 275 000 characters

The recursive solutions RA and RB gives

RangeError: Maximum call stack size exceeded

For 1M characters they even break Chrome

https://i.stack.imgur.com/dNkYp.png

I try to perform tests for 1M characters for other solutions, but E,F,G,H takes so much time that browser ask me to break script so I shrink test string to 275K characters. You can run tests on your machine HERE. Results for Chrome

https://i.stack.imgur.com/0uEgk.png

Code used in tests

var t="Test abc test test abc test test test abc test test abc"; // .repeat(5000) var log = (version,result) => console.log(`${version}: ${result}`); function A(str) { return str.split('abc').join(''); } function B(str) { return str.split`abc`.join``; // my proposition } function C(str) { return str.replace(/abc/g, ''); } function D(str) { return str.replace(new RegExp("abc", "g"), ''); } function E(str) { while (str.indexOf('abc') !== -1) { str = str.replace('abc', ''); } return str; } function F(str) { while (str.indexOf('abc') !== -1) { str = str.replace(/abc/, ''); } return str; } function G(str) { while(str.includes("abc")) { str = str.replace('abc', ''); } return str; } // src: https://stackoverflow.com/a/56989553/860099 function H(str) { let i = -1 let find = 'abc'; let newToken = ''; if (!str) { if ((str == null) && (find == null)) return newToken; return str; } while (( i = str.indexOf( find, i >= 0 ? i + newToken.length : 0 )) !== -1 ) { str = str.substring(0, i) + newToken + str.substring(i + find.length); } return str; } // src: https://stackoverflow.com/a/22870785/860099 function RA(string, prevstring) { var omit = 'abc'; var place = ''; if (prevstring && string === prevstring) return string; prevstring = string.replace(omit, place); return RA(prevstring, string) } // src: https://stackoverflow.com/a/26107132/860099 function RB(str) { var find = 'abc'; var 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) + RB(st2, find, replace); } } return str; } log('A ', A(t)); log('B ', B(t)); log('C ', C(t)); log('D ', D(t)); log('E ', E(t)); log('F ', F(t)); log('G ', G(t)); log('H ', H(t)); log('RA', RA(t)); // use reccurence log('RB', RB(t)); // use reccurence

This snippet only presents codes used in tests. It not perform test itself!


Now this is one hell of an in depth answer! Thank you very much! Although, what I'm curious about is why the "new RegExp(...)" syntax gives that much of an improvement.
T
Termininja

Replacing single quotes:

function JavaScriptEncode(text){
    text = text.replace(/'/g,''')
    // More encode here if required

    return text;
}

c
csomakk
str = str.replace(new RegExp("abc", 'g'), "");

worked better for me than the above answers. so new RegExp("abc", 'g') creates a RegExp what matches all occurence ('g' flag) of the text ("abc"). The second part is what gets replaced to, in your case empty string (""). str is the string, and we have to override it, as replace(...) just returns result, but not overrides. In some cases you might want to use that.


Warning! This method work well for just simple cases, but NEVER can be a main option. E.g., in case of any RegExp Special Character .^$*+?()[{|\\ exist in your string, can not return the expected result.
C
Cole Lawrence

This is the fastest version that doesn't use regular expressions.

Revised jsperf

replaceAll = function(string, omit, place, prevstring) {
  if (prevstring && string === prevstring)
    return string;
  prevstring = string.replace(omit, place);
  return replaceAll(prevstring, omit, place, string)
}

It is almost twice as fast as the split and join method.

As pointed out in a comment here, this will not work if your omit variable contains place, as in: replaceAll("string", "s", "ss"), because it will always be able to replace another occurrence of the word.

There is another jsperf with variants on my recursive replace that go even faster (http://jsperf.com/replace-all-vs-split-join/12)!

Update July 27th 2017: It looks like RegExp now has the fastest performance in the recently released Chrome 59.


n
nik7

Loop it until number occurrences comes to 0, like this:

function replaceAll(find, replace, str) {
    while (str.indexOf(find) > -1) {
        str = str.replace(find, replace);
    }
    return str;
}

This method is dangerous, do not use it. If the replacement string contains the search keyword, then an infinite loop will occur. At the very least, store the result of .indexOf in a variable, and use this variable as the second parameter of .indexOf (minus length of keyword, plus length of replacement string).
p
pitust

If what you want to find is already in a string, and you don't have a regex escaper handy, you can use join/split:

function replaceMulti(haystack, needle, replacement) { return haystack.split(needle).join(replacement); } someString = 'the cat looks like a cat'; console.log(replaceMulti(someString, 'cat', 'dog'));


T
Tim Rivoli
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;
}

P
Peter Mortensen

I like this method (it looks a little cleaner):

text = text.replace(new RegExp("cat","g"), "dog"); 

p
pkdkk
var str = "ff ff f f a de def";
str = str.replace(/f/g,'');
alert(str);

http://jsfiddle.net/ANHR9/


z
zdennis
while (str.indexOf('abc') !== -1)
{
    str = str.replace('abc', '');
}

R
Ran Marciano

The simplest way to this without using any regex is split and join like the code here:

var str = "Test abc test test abc test test test abc test test abc"; console.log(str.split('abc').join(''));


R
Ran Turner

String.prototype.replaceAll - ECMAScript 2021

The new String.prototype.replaceAll() method returns a new string with all matches of a pattern replaced by a replacement. The pattern can be either a string or a RegExp, and the replacement can be either a string or a function to be called for each match.

const message = 'dog barks meow meow'; const messageFormatted = message.replaceAll('meow', 'woof') console.log(messageFormatted);


replaceAll has already been suggested in almost 20 other answers and comments, including the accepted answer and the top-voted answer. What does this add?
If you're looking for the method in Node.js, this will not work. replit.com/@RixTheTyrunt/rixxyplayer-parser?v=1
@RixTheTyrunt Of course this will work in an up-to-date version of Node.js.
3
3 revs, 2 users 78%

If the string contain similar pattern like abccc, you can use this:

str.replace(/abc(\s|$)/g, "")

T
Thomas Orlita

As of August 2020 there is a Stage 4 proposal to ECMAScript that adds the replaceAll method to String.

It's now supported in Chrome 85+, Edge 85+, Firefox 77+, Safari 13.1+.

The usage is the same as the replace method:

String.prototype.replaceAll(searchValue, replaceValue)

Here's an example usage:

'Test abc test test abc test.'.replaceAll('abc', 'foo'); // -> 'Test foo test test foo test.'

It's supported in most modern browsers, but there exist polyfills:

core-js

es-shims

It is supported in the V8 engine behind an experimental flag --harmony-string-replaceall. Read more on the V8 website.


According to MDN, this has been available since Firefox 77 and Chromium 85.
P
Peter Mortensen

The previous answers are way too complicated. Just use the replace function like this:

str.replace(/your_regex_pattern/g, replacement_string);

Example:

var str = "Test abc test test abc test test test abc test test abc"; var res = str.replace(/[abc]+/g, ""); console.log(res);


S
SamGoody

If you are trying to ensure that the string you are looking for won't exist even after the replacement, you need to use a loop.

For example:

var str = 'test aabcbc';
str = str.replace(/abc/g, '');

When complete, you will still have 'test abc'!

The simplest loop to solve this would be:

var str = 'test aabcbc';
while (str != str.replace(/abc/g, '')){
   str.replace(/abc/g, '');
}

But that runs the replacement twice for each cycle. Perhaps (at risk of being voted down) that can be combined for a slightly more efficient but less readable form:

var str = 'test aabcbc';
while (str != (str = str.replace(/abc/g, ''))){}
// alert(str); alerts 'test '!

This can be particularly useful when looking for duplicate strings. For example, if we have 'a,,,b' and we wish to remove all duplicate commas. [In that case, one could do .replace(/,+/g,','), but at some point the regex gets complex and slow enough to loop instead.]


e
evandrix

Although people have mentioned the use of regex but there's a better approach if you want to replace the text irrespective of the case of the text. Like uppercase or lowercase. Use below syntax

//Consider below example
originalString.replace(/stringToBeReplaced/gi, '');

//Output will be all the occurrences removed irrespective of casing.

You can refer the detailed example here.


from the example site: "/toBeReplacedString/gi is the regex you need to use. Here g represents for global match and i represents case insensitive. By default regex is case sensitive"