Wie kann man alle Vorkommen eines Strings in JavaScript ersetzen?


Ich habe diese Zeichenfolge:

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

Tun

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

scheint nur das erste Vorkommen von abc in der obigen Kette zu entfernen. Wie kann ich alle Vorkommen ersetzen?


Answers



Der Vollständigkeit halber habe ich darüber nachgedacht, welche Methode ich dazu verwenden sollte. Es gibt grundsätzlich zwei Möglichkeiten, dies zu tun, wie von den anderen Antworten auf dieser Seite vorgeschlagen.

Hinweis: Im Allgemeinen wird das Erweitern der integrierten Prototypen in JavaScript im Allgemeinen nicht empfohlen. Ich gebe Erweiterungen für den String-Prototyp nur zum Zwecke der Veranschaulichung an und zeige verschiedene Implementierungen einer hypothetischen Standardmethode im integrierten Prototyp des String .

Reguläre ausdrucksbasierte Implementierung

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

Split und Join (funktionale) Implementierung

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

Da ich nicht zu sehr darüber informiert bin, wie reguläre Ausdrücke im Hinblick auf Effizienz hinter den Kulissen arbeiten, neigte ich dazu, mich der Spaltung anzunähern und an der Umsetzung in der Vergangenheit teilzunehmen, ohne über Leistung nachzudenken. Als ich mich fragte, was effizienter war, und in welchem ​​Umfang, benutzte ich es als Entschuldigung, um es herauszufinden.

Auf meiner Chrome Windows 8-Maschine ist die auf regulären Ausdrücken basierende Implementierung am schnellsten , da die Split- und Join-Implementierung 53% langsamer ist . Das bedeutet, dass die regulären Ausdrücke doppelt so schnell für den Lorem Ipsum-Eingang sind, den ich verwendet habe.

Schauen Sie sich diesen Benchmark an , der diese beiden Implementierungen gegeneinander ausführt.

Wie im folgenden Kommentar von @ThomasLeduc und anderen erwähnt, könnte es ein Problem mit der regulären ausdrucksbasierten Implementierung geben, wenn die search bestimmte Zeichen enthält, die in regulären Ausdrücken als Sonderzeichen reserviert sind. Bei der Implementierung wird davon ausgegangen, dass der Aufrufer die Zeichenfolge im Voraus maskiert oder Zeichenfolgen ohne die Zeichen in der Tabelle nur in regulären Ausdrücken ( Regular Expressions, MDN) übergeben wird.

MDN bietet auch eine Implementierung, um unseren Strings zu entkommen. Es wäre schön, wenn dies auch als RegExp.escape(str) genormt RegExp.escape(str) , aber leider existiert es nicht:

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

Wir könnten escapeRegExp innerhalb unserer String.prototype.replaceAll Implementierung String.prototype.replaceAll , ich bin mir jedoch nicht sicher, wie stark dies die Performance beeinträchtigen wird (möglicherweise sogar für Strings, für die das Escape nicht benötigt wird, wie alle alphanumerischen Strings).




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

Als Antwort auf einen Kommentar:

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

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

Als Antwort auf Click Upvotes Kommentar könnten Sie es noch einfacher machen:

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

Anmerkung: Reguläre Ausdrücke enthalten spezielle (Meta-) Zeichen, und daher ist es gefährlich, ein Argument in der obigen Suchfunktion blind weiterzuleiten, ohne es vorzubehandeln, um diese Zeichen zu umgehen. Dies wird im JavaScript-Handbuch für reguläre Ausdrücke des Mozilla Developer Network behandelt , wo sie die folgende Hilfsfunktion präsentieren:

function escapeRegExp(str) {
    return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}

Um die Funktion replaceAll() oben sicherer zu machen, könnte sie folgendermaßen geändert werden, wenn Sie auch escapeRegExp :

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



Hinweis: Verwenden Sie dieses nicht in echtem Code.

Als Alternative zu regulären Ausdrücken für eine einfache Literalzeichenfolge können Sie

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

Das allgemeine Muster ist

str.split(search).join(replacement)

Dies war in einigen Fällen schneller als die Verwendung von replaceAll und eines regulären Ausdrucks, aber das scheint in modernen Browsern nicht mehr der Fall zu sein. Also, dies sollte eigentlich nur als ein schneller Hack verwendet werden, um zu vermeiden, dass der reguläre Ausdruck entflieht, nicht in echtem Code.




Wenn Sie einen regulären Ausdruck mit dem Flag g set verwenden, werden alle ersetzt:

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

Siehe auch hier




Hier ist eine String-Prototyp-Funktion, die auf der akzeptierten Antwort basiert:

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

BEARBEITEN

Wenn Ihr find Sonderzeichen enthält, müssen Sie diesen entgehen:

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

Geige: http://jsfiddle.net/cdbzL/




Aktualisieren:

Es ist etwas spät für ein Update, aber da ich gerade auf diese Frage stolperte und bemerkte, dass meine vorherige Antwort nicht eine ist, mit der ich zufrieden bin. Da die Frage das Ersetzen eines einzelnen Wortes beinhaltete, ist es unglaublich niemand dachte daran, Wortgrenzen zu verwenden ( \b )

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

Dies ist eine einfache Regex, die es in den meisten Fällen vermeidet, Teile von Wörtern zu ersetzen. Ein Gedankenstrich wird jedoch immer noch als Wortgrenze betrachtet. So können in diesem Fall Bedingungen verwendet werden, um das Ersetzen von Strings wie cool-cat zu vermeiden:

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

Im Grunde ist diese Frage die gleiche wie die Frage hier: Javascript ersetzt "'" durch "' '"

@ Mike, überprüfen Sie die Antwort, die ich dort gab ... Regexp ist nicht die einzige Möglichkeit, mehrere Vorkommen eines Abonnements zu ersetzen, weit davon entfernt. Denken Sie flexibel, denken Sie gespalten!

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

Alternativ, um zu verhindern, dass Wortteile ersetzt werden - was auch die genehmigte Antwort tun wird! Sie können dieses Problem umgehen, indem Sie reguläre Ausdrücke verwenden, die, wie ich zugeben muss, etwas komplexer sind, und als Ergebnis davon ein bisschen langsamer:

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

Die Ausgabe ist die gleiche wie die akzeptierte Antwort, jedoch mit dem / cat / g-Ausdruck für diese Zeichenfolge:

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

Hoppla, das ist wahrscheinlich nicht das, was Sie wollen. Was ist dann? IMHO, eine Regex, die "cat" nur bedingt ersetzt. (also kein Teil eines Wortes), 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"

Meine Vermutung ist, dass dies Ihren Bedürfnissen entspricht. Es ist natürlich nicht vollständig, aber es sollte ausreichen, um den Anfang zu machen. Ich würde empfehlen, noch mehr auf diesen Seiten zu lesen. Dies wird sich als nützlich erweisen, wenn Sie diesen Ausdruck perfektionieren möchten, um Ihre spezifischen Anforderungen zu erfüllen.

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

http://www.regular-expressions.info

Letzte Ergänzung:

Da diese Frage immer noch viele Ansichten enthält, dachte ich, ich könnte ein Beispiel für .replace das mit einer Callback-Funktion verwendet wird. In diesem Fall vereinfacht es den Ausdruck dramatisch und bietet noch mehr Flexibilität, wie das Ersetzen durch korrekte Großschreibung oder das Ersetzen von cat und cats auf einen Schlag:

'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



Match gegen einen globalen regulären Ausdruck:

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



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

Oder versuchen Sie die Funktion replaceAll von hier aus:

Was sind nützliche JavaScript-Methoden, die eingebaute Objekte erweitern?

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

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

EDIT: Klarstellung über replaceAlle Verfügbarkeit

Die 'replaceAll'-Methode wird dem Prototyp von String hinzugefügt. Dies bedeutet, dass es für alle String-Objekte / Literale verfügbar ist.

Z.B

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



Verwenden Sie einen regulären Ausdruck:

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



Dies ist die schnellste Version, die keine regulären Ausdrücke verwendet .

Überarbeitetes jsperf

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

Es ist fast doppelt so schnell wie die Split- und Join-Methode.

Wie in einem Kommentar hier erwähnt, funktioniert dies nicht, wenn Ihre replaceAll("string", "s", "ss") einen place enthält, wie in: replaceAll("string", "s", "ss") , weil es immer ein anderes Vorkommen des Wortes ersetzen kann ..

Es gibt noch einen jsperf mit varianten auf meinem rekursiven replace, der noch schneller geht ( http://jsperf.com/replace-all-vs-split-join/12 )!

  • Update 27. Juli 2017: Es sieht so aus, als hätte RegExp jetzt die schnellste Leistung in dem kürzlich veröffentlichten Chrome 59.



// Schleife es, bis die Anzahl der Vorkommen auf 0 kommt. ODER einfach kopieren und einfügen

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



Sagen wir, Sie möchten alle 'abc' durch 'x' ersetzen:

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

Ich habe versucht, über etwas Einfacheres nachzudenken, als den String-Prototyp zu modifizieren.




Einfach...

Einfache Anführungszeichen ersetzen:

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;
}






Wenn das, was Sie finden wollen, bereits in einem String ist und Sie keinen Regex-Escaper zur Hand haben, können Sie join / split verwenden:

function replaceMulti(haystack, needle, replacement)
{
    return haystack.split(needle).join(replacement);
}

someString = 'the cat looks like a cat';
anotherString = replaceMulti(someString, 'cat', 'dog');



Ich mag diese Methode (sie sieht etwas sauberer aus):

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



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



Wenn Sie versuchen, sicherzustellen, dass die Zeichenfolge, nach der Sie suchen, auch nach dem Ersetzen nicht vorhanden ist, müssen Sie eine Schleife verwenden.

Beispielsweise:

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

Wenn Sie fertig sind, haben Sie immer noch 'test abc'!

Die einfachste Schleife zur Lösung dieses Problems wäre:

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

Aber das führt den Ersatz zweimal für jeden Zyklus aus. Vielleicht (mit der Gefahr, herabgestimmt zu werden), die man zu einer etwas effizienteren, aber weniger lesbaren Form kombinieren kann:

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

Dies kann besonders nützlich sein, wenn Sie nach doppelten Strings suchen.
Zum Beispiel, wenn wir 'a ,,, b' haben und möchten alle doppelten Kommas entfernen.
[In diesem Fall könnte man .replace (/, + / g, ',') verwenden, aber irgendwann wird die Regex komplex und langsam genug, um stattdessen zu loopen.]




Sie können einfach unter der folgenden Methode verwenden

/**
 * 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);
};



Obwohl Leute die Verwendung von Regex erwähnt haben, gibt es einen besseren Ansatz, wenn Sie den Text ungeachtet des Falls des Textes ersetzen möchten. Wie Großbuchstaben oder Kleinbuchstaben. Verwenden Sie die folgende Syntax

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

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

Sie können das ausführliche Beispiel hier verweisen.




Einfach hinzufügen /g

document.body.innerHTML = document.body.innerHTML.replace('hello', 'hi');

zu

// Replace 'hello' string with /hello/g regular expression.
document.body.innerHTML = document.body.innerHTML.replace(/hello/g, 'hi');

/g bedeutet global




Folgende Funktion funktioniert für mich:

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);
} ;

Rufe jetzt die Funktionen wie folgt auf:

"you could be a Project Manager someday, if you work like this.".replaceAllOccurence ("you", "I");

Kopieren Sie einfach diesen Code und fügen Sie ihn in Ihrer Browser-Konsole in TEST ein.




Meine Umsetzung, sehr selbsterklärend

function replaceAll(string, token, newtoken) {
    if(token!=newtoken)
    while(string.indexOf(token) > -1) {
        string = string.replace(token, newtoken);
    }
    return string;
}



Ich verwende p , um das Ergebnis aus dem vorherigen Rekursionsaustausch zu speichern:

function replaceAll(s, m, r, p) {
    return s === p || r.contains(m) ? s : replaceAll(s.replace(m, r), m, r, s);
}

Es ersetzt alle Vorkommen in der Zeichenkette s, bis es möglich ist:

replaceAll('abbbbb', 'ab', 'a')  'abbbb'  'abbb'  'abb'  'ab'  'a'

Um die Endlosschleife zu vermeiden, überprüfe ich, ob der Ersatz r eine Übereinstimmung m enthält:

replaceAll('abbbbb', 'a', 'ab')  'abbbbb'



Die meisten Leute tun dies wahrscheinlich, um eine URL zu kodieren. Um eine URL zu codieren, sollten Sie nicht nur Leerzeichen berücksichtigen, sondern die gesamte Zeichenfolge mit encodeURI richtig encodeURI .

encodeURI("http://www.google.com/a file with spaces.html")

bekommen:

http://www.google.com/a%20file%20with%20spaces.html



Wenn der String ähnliche Muster wie abccc enthält, verwenden Sie:

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



Um alle Arten von Zeichen zu ersetzen, versuchen Sie diesen Code:

Suppose we have need to send " and \ in my string, then we will convert it " to \" and \ to \\

Diese Methode wird also dieses Problem lösen.

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 \\"*/

Ich verwendete Ajax und musste Parameter im JSON-Format senden. Dann sieht meine Methode so aus:

 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);
 };



Wenn die Verwendung einer Bibliothek eine Option für Sie ist, werden Sie die Vorteile des Tests und der Community-Unterstützung erhalten, die mit einer Bibliotheksfunktion einhergeht. Zum Beispiel hat die Bibliothek string.js eine replaceAll () -Funktion, die genau das tut, wonach Sie suchen:

// 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;
}