Come sostituire tutte le occorrenze di una stringa in JavaScript?


Ho questa stringa:

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

fare

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

sembra rimuovere solo la prima occorrenza di abc nella stringa sopra. Come posso sostituire tutte le occorrenze di esso?



Answers



Per completezza, ho avuto modo di pensare a quale metodo dovrei usare per farlo. Ci sono fondamentalmente due modi per farlo come suggerito dalle altre risposte in questa pagina.

Nota: in generale, l'estensione dei prototipi incorporati in JavaScript non è generalmente raccomandata. Sto fornendo come estensioni sul prototipo di String semplicemente per scopi illustrativi, mostrando diverse implementazioni di un ipotetico metodo standard sul prototipo di String built-in.

Esecuzione basata su espressioni regolari

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

Implementazione divisa e join (funzionale)

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

Non sapendo troppo su come le espressioni regolari funzionino dietro le quinte in termini di efficienza, tendevo a propendere per la divisione e unire l'implementazione in passato senza pensare alle prestazioni. Quando mi sono chiesto quale fosse più efficiente e con quale margine, l'ho usato come scusa per scoprirlo.

Sul mio computer Windows 8 di Chrome, l'implementazione basata su espressioni regolari è la più veloce , con l' implementazione di divisioni e join più lenta del 53% . Significa che le espressioni regolari sono due volte più veloci per l'ingresso di lorem ipsum che ho usato.

Dai un'occhiata a questo benchmark che esegue queste due implementazioni l'una contro l'altra.

Come notato nel commento seguente di @ThomasLeduc e altri, potrebbe esserci un problema con l'implementazione basata su espressioni regolari se la search contiene determinati caratteri che sono riservati come caratteri speciali nelle espressioni regolari . L'implementazione presuppone che il chiamante sfugga alla stringa in anticipo o passerà solo le stringhe senza i caratteri nella tabella in Regular Expressions (MDN).

MDN fornisce anche un'implementazione per sfuggire alle nostre stringhe. Sarebbe bello se questo fosse anche standardizzato come RegExp.escape(str) , ma purtroppo non esiste:

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

Potremmo chiamare escapeRegExp all'interno della nostra implementazione String.prototype.replaceAll , tuttavia, non sono sicuro di quanto questo influenzi le prestazioni (potenzialmente anche per le stringhe per cui l'escape non è necessario, come tutte le stringhe alfanumeriche).




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

In risposta al commento:

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

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

In risposta al commento di Click Upvote , puoi semplificarlo ancora di più:

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

Nota: le espressioni regolari contengono caratteri speciali (meta) e in quanto tale è pericoloso passare ciecamente un argomento nella funzione di find sopra senza pre-elaborarlo per sfuggire a quei caratteri. Questo è spiegato nella Guida JavaScript di Mozilla Developer Network su Espressioni regolari , in cui vengono presentate le seguenti funzioni di utilità:

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

Quindi, per rendere la funzione replaceAll() sopra più sicura, potrebbe essere modificata alla seguente se si include anche escapeRegExp :

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



Nota: non usare questo nel codice reale.

In alternativa alle espressioni regolari per una semplice stringa letterale, puoi usare

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

Lo schema generale è

str.split(search).join(replacement)

In alcuni casi questo replaceAll era più veloce dell'uso di replaceAll e un'espressione regolare, ma non sembra più il caso nei browser moderni. Quindi, questo dovrebbe essere usato solo come un trucco rapido per evitare di dover sfuggire all'espressione regolare, non nel codice reale.




L'uso di un'espressione regolare con il flag g set sostituirà tutto:

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

Vedi anche qui




Ecco una funzione di prototipo di stringa basata sulla risposta accettata:

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

MODIFICARE

Se la tua find conterrà caratteri speciali, dovrai sfuggire a loro:

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

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




Aggiornare:

È un po 'tardi per un aggiornamento, ma da quando mi sono imbattuto in questa domanda e ho notato che la mia risposta precedente non è una di cui sono felice. Dal momento che la domanda riguardava la sostituzione di una singola parola, è incredibile che nessuno pensasse di usare i limiti delle parole ( \b )

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

Questa è una semplice regex che evita di sostituire parti di parole nella maggior parte dei casi. Tuttavia, un trattino - è ancora considerato un limite di parole. Quindi i condizionali possono essere usati in questo caso per evitare di sostituire stringhe come 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"

fondamentalmente, questa domanda è la stessa della domanda qui: Javascript sostituisce "'" con "' '"

@ Mike, controlla la risposta che ho dato lì ... regexp non è l'unico modo per sostituire più occorrenze di un subsrting, lontano da esso. Pensa flessibile, pensa dividi!

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

In alternativa, per evitare la sostituzione di parti di parole, cosa che farà anche la risposta approvata! Puoi aggirare questo problema usando espressioni regolari che, lo ammetto, sono un po 'più complesse e, come risultato, anche un po' più lento:

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

L'output è uguale alla risposta accettata, tuttavia, usando l'espressione / cat / g su questa stringa:

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

Oso davvero, questo probabilmente non è quello che vuoi. Cos'è, allora? IMHO, una regex che sostituisce solo "gatto" in modo condizionale. (cioè non parte di una parola), in questo modo:

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"

La mia ipotesi è che questo soddisfi le tue esigenze. Naturalmente non è completamente protetto, ma dovrebbe essere sufficiente per iniziare. Consiglierei di leggerne un po 'di più su queste pagine. Ciò si rivelerà utile per perfezionare questa espressione per soddisfare le tue esigenze specifiche.

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

http://www.regular-expressions.info

Aggiunta finale:

Dato che questa domanda ottiene ancora molte visualizzazioni, ho pensato di aggiungere un esempio di .replace utilizzato con una funzione di callback. In questo caso, semplifica drasticamente l'espressione e offre una flessibilità ancora maggiore, come la sostituzione con la corretta maiuscola o la sostituzione di cat e cats in una volta sola:

'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



Corrisponde a un'espressione regolare globale:

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



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

Oppure prova la funzione replaceAll da qui:

Quali sono i metodi JavaScript utili che estendono gli oggetti incorporati?

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

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

EDIT: chiarimenti sulla sostituzione di tutte le disponibilità

Il metodo 'replaceAll' viene aggiunto al prototipo di String. Ciò significa che sarà disponibile per tutti gli oggetti stringa / letterali.

Per esempio

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



Usa un'espressione regolare:

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



Questa è la versione più veloce che non usa espressioni regolari .

Revisionato jsperf

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

È quasi due volte più veloce del metodo split e join.

Come indicato in un commento qui, questo non funzionerà se la variabile replaceAll("string", "s", "ss") contiene la place , come in: replaceAll("string", "s", "ss") , perché sarà sempre in grado di sostituire un'altra occorrenza della parola .

C'è un altro jsperf con varianti sul mio sostituto ricorsivo che vanno ancora più veloce ( http://jsperf.com/replace-all-vs-split-join/12 )!

  • Aggiornamento 27 luglio 2017: sembra che RegExp abbia ora le prestazioni più veloci nel Chrome 59 rilasciato di recente.



// loop fino a quando le occorrenze del numero arrivano a 0. OPPURE semplicemente copia / incolla

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



Supponi di voler sostituire tutti 'abc' con '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

Stavo cercando di pensare a qualcosa di più semplice della modifica del prototipo di stringa.




Semplice...

Sostituire le virgolette singole:

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






Se ciò che vuoi trovare è già in una stringa, e non hai una scrittura regolare, puoi usare 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');



Mi piace questo metodo (sembra un po 'più pulito):

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



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



Se stai cercando di assicurarti che la stringa che stai cercando non esista nemmeno dopo la sostituzione, devi usare un loop.

Per esempio:

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

Al termine, avrai ancora 'test abc'!

Il ciclo più semplice per risolvere questo sarebbe:

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

Ma questo esegue la sostituzione due volte per ogni ciclo. Forse (a rischio di essere votati in ribasso) che può essere combinato per una forma leggermente più efficiente ma meno leggibile:

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

Questo può essere particolarmente utile quando cerchi stringhe duplicate.
Ad esempio, se abbiamo 'a ,,, b' e desideriamo rimuovere tutte le virgole duplicate.
[In tal caso, si potrebbe fare .replace (/, + / g, ','), ma a un certo punto la regex diventa complessa e abbastanza lenta da eseguire il loop.]




Puoi semplicemente usare sotto il metodo

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



Sebbene la gente abbia menzionato l'uso della regex ma c'è un approccio migliore se si vuole sostituire il testo indipendentemente dal caso del testo. Come maiuscole o minuscole. Usa sotto la sintassi

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

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

Puoi fare riferimento all'esempio dettagliato qui .




Basta aggiungere /g

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

a

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

/g significa globale




La seguente funzione funziona per me:

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

ora chiama le funzioni in questo modo:

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

Basta copiare e incollare questo codice nella tua console del browser su TEST.




La mia implementazione, molto esplicativa

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



Io uso p per memorizzare il risultato della precedente ricorsione:

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

Sostituirà tutte le occorrenze nella stringa s finché non sarà possibile:

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

Per evitare loop infiniti, controllo se la sostituzione r contiene una corrispondenza m :

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



La maggior parte delle persone probabilmente lo fa per codificare un URL. Per codificare un URL, non dovresti prendere in considerazione solo gli spazi, ma convertire correttamente l'intera stringa con encodeURI .

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

ottenere:

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



Se la stringa contiene pattern simili come abccc usa:

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



Per sostituire tutti i tipi di caratteri, prova questo codice:

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

Quindi questo metodo risolverà questo problema.

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

Stavo usando Ajax e ho avuto bisogno di inviare parametri in formato JSON. Quindi il mio metodo è simile a questo:

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



Se l'utilizzo di una libreria è un'opzione per te, otterrai i vantaggi del testing e del supporto della community che si accompagnano a una funzione di libreria. Ad esempio, la libreria string.js ha una funzione replaceAll () che fa ciò che stai cercando:

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