5465 Stimmen

Ersetzen aller Vorkommen einer Zeichenkette in JavaScript

Ich habe diese Zeichenfolge in meinem JavaScript-Code:

"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 Zeichenfolge.

Wie kann ich die alle Vorkommnisse davon?

20voto

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

18voto

MMMahdy-PAPION Punkte 487

Natürlich in 2021 ist die richtige Antwort:

String.prototype.replaceAll()

console.log(
  'Change this and this for me'.replaceAll('this','that') // Normal case
);
console.log(
  'aaaaaa'.replaceAll('aa','a') // Challenged case
);

Wenn Sie keine Lust haben, sich mit ersetzen() + RegExp .

Was aber, wenn der Browser <2020 ist?

In diesem Fall benötigen wir Polyfill (Zwingt ältere Browser, neue Funktionen zu unterstützen) (Ich denke, für ein paar Jahre notwendig sein)
Ich konnte keine völlig richtige Methode in den Antworten finden. Daher schlage ich diese Funktion vor, die als Polyfill definiert werden soll.

Meine vorgeschlagenen Optionen für replaceAll Polyfill:

replaceAll polyfill (Mit global-flag Fehler) [Prinzipiellere Version]
if (!String.prototype.replaceAll) { // Check if the native function not exist
    Object.defineProperty(String.prototype, 'replaceAll', { // Define replaceAll as a prototype for (Mother/Any) String
        configurable: true, writable: true, enumerable: false, // Editable & non-enumerable property (As it should be)
        value: function(search, replace) { // Set the function by closest input names (For good info in consoles)
            return this.replace( // Using native String.prototype.replace()
                Object.prototype.toString.call(search) === '[object RegExp]' // IsRegExp?
                    ? search.global // Is the RegEx global?
                        ? search // So pass it
                        : function(){throw new TypeError('replaceAll called with a non-global RegExp argument')}() // If not throw an error
                    : RegExp(String(search).replace(/[.^$*+?()[{|\\]/g, "\\$&"), "g"), // Replace all reserved characters with '\' then make a global 'g' RegExp
                replace); // passing second argument
        }
    });
}
replaceAll Polyfill (mit der Handhabung des fehlenden Global-Flags selbst) [Meine erste Präferenz] - Warum?
if (!String.prototype.replaceAll) { // Check if the native function not exist
    Object.defineProperty(String.prototype, 'replaceAll', { // Define replaceAll as a prototype for (Mother/Any) String
        configurable: true, writable: true, enumerable: false, // Editable & non-enumerable property (As it should be)
        value: function(search, replace) { // Set the function by closest input names (For good info in consoles)
            return this.replace( // Using native String.prototype.replace()
                Object.prototype.toString.call(search) === '[object RegExp]' // IsRegExp?
                    ? search.global // Is the RegEx global?
                        ? search // So pass it
                        : RegExp(search.source, /\/([a-z]*)$/.exec(search.toString())[1] + 'g') // If not, make a global clone from the RegEx
                    : RegExp(String(search).replace(/[.^$*+?()[{|\\]/g, "\\$&"), "g"), // Replace all reserved characters with '\' then make a global 'g' RegExp
                replace); // passing second argument
        }
    });
}
Minified [Meine erste Präferenz]:
if(!String.prototype.replaceAll){Object.defineProperty(String.prototype,'replaceAll',{configurable:!0,writable:!0,enumerable:!1,value:function(search,replace){return this.replace(Object.prototype.toString.call(search)==='[object RegExp]'?search.global?search:RegExp(search.source,/\/([a-z]*)$/.exec(search.toString())[1]+'g'):RegExp(String(search).replace(/[.^$*+?()[{|\\]/g,"\\$&"),"g"),replace)}})}
Versuchen Sie es:
if(!String.prototype.replaceAll){Object.defineProperty(String.prototype,'replaceAll',{configurable:!0,writable:!0,enumerable:!1,value:function(search,replace){return this.replace(Object.prototype.toString.call(search)==='[object RegExp]'?search.global?search:RegExp(search.source,/\/([a-z]*)$/.exec(search.toString())[1]+'g'):RegExp(String(search).replace(/[.^$*+?()[{|\\]/g,"\\$&"),"g"),replace)}})}

console.log(
  'Change this and this for me'.replaceAll('this','that')
); // Change that and that for me

console.log(
  'aaaaaa'.replaceAll('aa','a')
); // aaa

console.log(
  '{} (*) (*) (RegEx) (*) (\*) (\\*) [reserved characters]'.replaceAll('(*)','X')
); // {} X X (RegEx) X X (\*) [reserved characters]

console.log(
  'How (replace) (XX) with $1?'.replaceAll(/(xx)/gi,'$$1')
); // How (replace) ($1) with $1?

console.log(
  'Here is some numbers 1234567890 1000000 123123.'.replaceAll(/\d+/g,'***')
); // Here is some numbers *** *** *** and need to be replaced.

console.log(
  'Remove numbers under 233: 236   229  711   200   5'.replaceAll(/\d+/g, function(m) {
    return parseFloat(m) < 233 ? '' : m
  })
); // Remove numbers under 233: 236     711

console.log(
  'null'.replaceAll(null,'x')
); // x

// The difference between My first preference and the original:
// Now in 2022 with browsers > 2020 it should throw an error (But possible it be changed in future)

//   console.log(
//      'xyz ABC abc ABC abc xyz'.replaceAll(/abc/i,'')
//   );

// Browsers < 2020:
// xyz     xyz
// Browsers > 2020
// TypeError: String.prototype.replaceAll called with a non-global RegExp
Browser-Unterstützung:

IE 9+ (Getestet mit IE11)
Alle anderen Browser (nach 2012)

Das Ergebnis ist dasselbe wie das native replaceAll im Falle des ersten Arguments Eingabe sein:
null , undefined , Object , Function , Date , ... , RegExp , Number , String , ...

Ref: https://tc39.es/ecma262/#sec-string.prototype.replaceall _+ RegExp-Syntax_

Wichtiger Hinweis: Wie von einigen Fachleuten erwähnt, liefern viele der rekursiven Funktionen, die in den Antworten vorgeschlagen werden, ein falsches Ergebnis. (Probieren Sie sie mit dem herausgeforderten Fall des obigen Ausschnitts aus)
Vielleicht einige knifflige Methoden wie .split('searchValue').join('replaceValue') oder Einige gut verwaltete Funktionen liefern das gleiche Ergebnis, aber definitiv viel weniger Leistung als native replaceAll() / polyfill replaceAll() / replace() + RegExp


Andere Methoden der Polyfill-Zuweisung

Naiv, aber unterstützt auch Ältere (besser zu vermeiden)

Wir können zum Beispiel auch IE7+ unterstützen, indem wir nicht Object.defineProperty() und meine alte naive Zuweisungsmethode anwenden:

if (!String.prototype.replaceAll) {
    String.prototype.replaceAll = function(search, replace) { // <-- Naive method for assignment
        // ... (Polyfill code Here)
    }
}

Und es sollte für grundlegende Anwendungen im IE7+ gut funktionieren.
Aber als aquí @sebastian-simon erläuterte, die bei weitergehenden Anwendungen zu sekundären Problemen führen können. Z.B.:

for (var k in 'hi') console.log(k);
// 0
// 1
// replaceAll  <-- ?
Vollkommen vertrauenswürdig, aber schwer

Die von mir vorgeschlagene Option ist sogar etwas optimistisch. Wie wir vertrauten die Umgebung (Browser/Node) ist definitiv für rund 2012-2021, auch ist ein Standard/Famous ein, so erfordern keine besondere Berücksichtigung.
Aber es kann sogar ältere Browser ODER einige unerwartete Probleme geben, und Polyfills können immer noch unterstützen und mehr mögliche Umgebungsprobleme lösen. Für den Fall, dass wir maximale Unterstützung benötigen, die möglich ist, können wir verwenden polyfill libraries mögen:

https://polyfill.io/

Speziell für replaceAll :

<script src="https://polyfill.io/v3/polyfill.min.js?features=String.prototype.replaceAll"></script>

18voto

Owen Punkte 3959

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

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

15voto

sajadre Punkte 1052

Der einfachste Weg, dies zu tun, ohne eine Regex zu verwenden, ist split and join wie der Code hier:

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

14voto

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

http://jsfiddle.net/ANHR9/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X