Comment remplacer toutes les occurrences d'une chaîne?

4384

J'ai cette chaîne:

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

Faire:

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

semble supprimer uniquement la première occurrence de abcdans la chaîne ci-dessus.

Comment puis-je en remplacer toutes les occurrences?

Cliquez Upvote
la source
5
Lors du remplacement de toutes les occurrences de abain ababapar ca, quel résultat attendez-vous? caba? abca? cca?
reinierpost
String.prototype.replaceAll()livré dans Safari 13.1 et est maintenant dans Firefox Nightly et Chrome Dev et Canary et sera livré dans Firefox 77 et Chrome 85. Ce n'est pas encore documenté dans MDN, mais github.com/tc39/proposal-string-replaceall#high-level-api a un explicateur: «Si searchValue est une chaîne, String.prototype.replaceAllremplace toutes les occurrences de searchValue (comme si .split(searchValue).join(replaceValue)ou une expression régulière globale et correctement échappée avait été utilisée). Si searchValue est une expression régulière non globale, String.prototype.replaceAlllève une exception »
sideshowbarker

Réponses:

1612

Remarque: Ne l'utilisez pas dans un code critique pour les performances.

Comme alternative aux expressions régulières pour une chaîne littérale simple, vous pouvez utiliser

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

Le schéma général est

str.split(search).join(replacement)

Dans certains cas, cela était plus rapide que l'utilisation replaceAllet une expression régulière, mais cela ne semble plus être le cas dans les navigateurs modernes.

Indice de référence: https://jsperf.com/replace-all-vs-split-join

Conclusion: si vous avez un cas d'utilisation critique pour les performances (par exemple, le traitement de centaines de chaînes), utilisez la méthode Regexp. Mais pour la plupart des cas d'utilisation typiques, cela vaut la peine de ne pas avoir à se soucier des caractères spéciaux.

Matthew Crumley
la source
147
Cela m'a surpris, car je m'attendais à ce que cette méthode alloue plus d'objets, créant plus de déchets, et donc prenne plus de temps, mais lorsque j'ai effectivement testé dans un navigateur, cette méthode était toujours environ 20% plus rapide que la réponse acceptée. Les résultats peuvent bien sûr varier.
MgSam
42
J'étais moi-même curieux et j'ai créé ceci: jsperf.com/replace-all-vs-split-join . Il semble que la v8 soit juste très rapide pour fractionner / joindre des tableaux par rapport à d'autres moteurs javascript.
fabi
8
Très agréable - vous évite également la possibilité de mauvais RegExps lors du passage de caractères spéciaux. J'ajoute un indicateur générique pour "trouver ceci et le remplacer" dans une propriété d'objet, mais je me demandais si je devais remplacer "." ou "}" et j'ai oublié que j'utilisais RegEx 3 mois plus tard!
tobriand le
9
Et comme String.prototype: String.prototype.replaceAll = function(f,r){return this.split(f).join(r);}. Utilisation: "My string".replaceAll('st', '');produit "Mon anneau"
MacroMan
8
Je ne vois pas de raison pour l'avertissement de ne pas l'utiliser en production. Ce n'est pas plus un hack que d'échapper à une expression régulière simplement parce que vous voulez remplacer plusieurs occurrences, mais n'avez pas besoin d'une expression régulière en premier lieu. Enveloppez simplement ce soi-disant "hack" dans une belle replaceAllfonction, et cela devient tout aussi lisible que toute autre chose. Comme les performances ne sont pas mauvaises, il n'y a aucune raison d'éviter cette solution.
youen
4385
str = str.replace(/abc/g, '');

En réponse au commentaire:

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

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

En réponse au commentaire de Click Upvote , vous pouvez le simplifier encore plus:

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

Remarque: Les expressions régulières contiennent des caractères (méta) spéciaux, et en tant que tel, il est dangereux de passer aveuglément un argument dans la findfonction ci-dessus sans le pré-traiter pour échapper à ces caractères. Ceci est couvert dans le Developer Network Mozilla de JavaScript Guide sur les expressions régulières , où ils présentent la fonction d'utilité suivante (qui a changé au moins deux fois depuis cette réponse a été écrit à l' origine, alors assurez - vous de consulter le site MDN pour les mises à jour possibles):

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

Ainsi, afin de rendre la replaceAll()fonction ci-dessus plus sûre, elle pourrait être modifiée comme suit si vous incluez également escapeRegExp:

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Sean Bright
la source
4
Les expressions régulières sont le seul moyen d'accomplir cette opération "hors de la boîte" sans implémenter votre propre méthode 'replaceAll'. Je ne suggère pas leur utilisation juste pour le plaisir de les utiliser.
Sean Bright
10
Ceci est ma propre fonction de ce commentaire: function replaceAll(find, replace,str) { var re = new RegExp(find, 'g'); str = str.replace(re, replace); return str; }
Cliquez sur Upvote
47
La mise en garde majeure de l' replaceAllimplémentation est qu'elle ne fonctionnera pas si findcontient des métacaractères.
Martin Ender
1
@SeanBright vous avez raison. J'ai utilisé votre javascript dans un code php, j'ai donc dû ajouter une barre oblique inverse supplémentaire pour s'échapper. Au violon, votre code est parfait. J'aurais dû vérifier. Excuses jsfiddle.net/7y19xyq8
Onimusha
2437

Par souci d'exhaustivité, j'ai réfléchi à la méthode à utiliser pour ce faire. Il existe essentiellement deux façons de procéder, comme le suggèrent les autres réponses de cette page.

Remarque: En général, l'extension des prototypes intégrés en JavaScript n'est généralement pas recommandée. Je fournis des extensions sur le prototype String simplement à des fins d'illustration, montrant différentes implémentations d'une méthode standard hypothétique sur le Stringprototype intégré.


Implémentation basée sur l'expression régulière

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

Implémentation de Split and Join (fonctionnelle)

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

Ne sachant pas trop comment les expressions régulières fonctionnent en arrière-plan en termes d'efficacité, j'ai eu tendance à pencher vers la séparation et à rejoindre la mise en œuvre dans le passé sans penser aux performances. Quand je me suis demandé ce qui était le plus efficace et par quelle marge, je l'ai utilisé comme excuse pour le découvrir.

Sur ma machine Chrome Windows 8, l'implémentation basée sur l'expression régulière est la plus rapide , l' implémentation de scission et de jointure étant 53% plus lente . Cela signifie que les expressions régulières sont deux fois plus rapides pour l'entrée lorem ipsum que j'ai utilisée.

Découvrez ce benchmark exécutant ces deux implémentations l'une contre l'autre.


Comme indiqué dans le commentaire ci-dessous par @ThomasLeduc et d'autres, il pourrait y avoir un problème avec l'implémentation basée sur une expression régulière si elle searchcontient certains caractères qui sont réservés en tant que caractères spéciaux dans les expressions régulières . L'implémentation suppose que l'appelant échappera au préalable à la chaîne ou ne transmettra que les chaînes qui ne contiennent pas les caractères du tableau dans les expressions régulières (MDN).

MDN fournit également une implémentation pour échapper à nos chaînes. Ce serait bien si cela était également standardisé car RegExp.escape(str), hélas, cela n'existe pas:

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

Nous pourrions appeler escapeRegExpdans notre String.prototype.replaceAllimplémentation, cependant, je ne sais pas dans quelle mesure cela affectera les performances (potentiellement même pour les chaînes pour lesquelles l'échappement n'est pas nécessaire, comme toutes les chaînes alphanumériques).

Cory Gross
la source
8
Sur Android 4.1, la méthode d'expression régulière est 15% plus rapide, mais vous n'échappez pas à l'expression à rechercher, donc cette référence est incomplète.
andreszs
33
Il y a un problème avec cette solution, si votre chaîne de recherche semble contenir des caractères spéciaux d'une expression rationnelle, ils seront interprétés. Je recommande la réponse @Sandy Unitedwolf.
Thomas Leduc
2
Le premier fera ceci: 'bla.bla'.replaceAll ('. ',' _ '); "_______". Le second fera 'bla_bla', ce qui est plus généralement ce que vous voulez faire.
RobKohr
1
@ThomasLeduc il semble que le problème que vous avez mentionné puisse être résolu avec lodash => lodash.com/docs/4.17.5#escapeRegExp
Matthew Beck
1
Laissant cela ici pour les futurs téléspectateurs qui se demandent également pourquoi étendre l'objet natif est une mauvaise idée: stackoverflow.com/questions/14034180/…
Ben Cooper
692

L'utilisation d'une expression régulière avec le gjeu d'indicateurs remplacera tout:

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

Voir ici aussi

Adam A
la source
15
Un peu idiot, je pense, mais le regex mondial JS est le seul moyen de faire plusieurs remplacements.
Mike
5
eh bien techniquement, vous pouvez parcourir var sourceTextle nombre d'instances ( numOfInstances) en utilisant substringou diviser et compter la longueur (entre autres stratégies), thatWhichYouWantToReplacepuis faire for (var i = 0; i < numOfInstances; i++){ sourceText = sourceText.replace('thatWhichYouWantToReplace', '');} ou encore plus simplement utiliser une boucle while ( while sourceText.indexOf(thatWhichYouWantToReplace > -1){ sourceText = sourceText.replace(...)) mais je ne vois pas pourquoi vous voudriez faire de cette façon lors de l'utilisation /gest si facile et probablement plus performant.
Zargold
@Zargold Vous voudriez faire une boucle pour vous assurer que même après le remplacement, vous avez remplacé toutes les instances, ce qui est un piège assez courant. Voir ma réponse ci-dessous stackoverflow.com/a/26089052/87520
SamGoody
109

Voici une fonction de prototype de chaîne basée sur la réponse acceptée:

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

ÉDITER

Si votre findcontient des caractères spéciaux, vous devez les échapper:

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

Violon: http://jsfiddle.net/cdbzL/

jesal
la source
5
Mais que se passe-t-il si findcontient des caractères comme .ou $qui ont des significations spéciales dans l'expression régulière?
callum
1
@callum Dans ce cas, vous devez échapper à votre variable find (voir modification ci-dessus).
jesal
jesal, c'est une merveilleuse solution à un problème de remplacement de chaîne que j'ai rencontré, et cela surmonte apparemment l '"immuabilité" des chaînes en JavaScript. Pourriez-vous ou quelqu'un d'autre expliquer comment cette fonction prototype l'emporte sur l'immuabilité des chaînes? Cela fait le travail; Je veux juste comprendre cette question accessoire qu'elle pose.
Tom
1
@Tom: Il ne surmonte pas du tout l'immuabilité: var str = thiscrée une deuxième référence à la chaîne immuable, à laquelle la replaceméthode est appliquée, qui retourne à son tour une nouvelle chaîne immuable . ces fonctions prototypes renvoient une nouvelle chaîne immuable, sinon, vous seriez en mesure d'écrire someStrVar.replaceAll('o', '0');et vous someStrVarseriez modifié. Au lieu de cela, vous devez écrire someStrVar = someStrVar.replaceAll('o', '0');<- réaffecter pour définir le var pour contenir la nouvelle chaîne immuable . il n'y a aucun moyen de contourner cela. Essayez en console:x = 'foobar'; x.replaceAll('o', '0'); x;
Elias Van Ootegem
87

Mise à jour:

Il est un peu tard pour une mise à jour, mais comme je suis juste tombé sur cette question et que j'ai remarqué que ma réponse précédente n'est pas celle dont je suis satisfait. Étant donné que la question impliquait de remplacer un seul mot, il est incroyable que personne n'ait pensé à utiliser les limites des mots ( \b)

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

Il s'agit d'une expression régulière simple qui évite de remplacer des parties de mots dans la plupart des cas. Cependant, un tiret -est toujours considéré comme une limite de mot. Les conditions peuvent donc être utilisées dans ce cas pour éviter de remplacer des chaînes comme 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"

en gros, cette question est la même que la question ici: Javascript remplace "'" par "' '"

@Mike, vérifiez la réponse que j'ai donnée là-bas ... regexp n'est pas le seul moyen de remplacer plusieurs occurrences d'une souscription, loin de là. Pensez flexible, pensez divisé!

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

Alternativement, pour éviter de remplacer des parties de mots - ce que la réponse approuvée fera aussi! Vous pouvez contourner ce problème en utilisant des expressions régulières qui sont, je l'admets, un peu plus complexes et, en conséquence, un peu plus lentes aussi:

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

La sortie est la même que la réponse acceptée, cependant, en utilisant l'expression / cat / g sur cette chaîne:

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

Oups en effet, ce n'est probablement pas ce que vous voulez. Qu'est-ce donc? À mon humble avis, une expression régulière qui ne remplace que «chat» conditionnellement. (c'est-à-dire ne faisant pas partie d'un mot), comme ceci:

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"

Je suppose que cela répond à vos besoins. Ce n'est pas complet, bien sûr, mais cela devrait suffire pour vous aider à démarrer. Je recommanderais de lire un peu plus sur ces pages. Cela s'avérera utile pour perfectionner cette expression pour répondre à vos besoins spécifiques.

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

http://www.regular-expressions.info


Ajout final:

Étant donné que cette question obtient toujours beaucoup de vues, j'ai pensé que je pourrais ajouter un exemple d' .replaceutilisation avec une fonction de rappel. Dans ce cas, il simplifie considérablement l'expression et offre encore plus de flexibilité, comme le remplacement par une capitalisation correcte ou le remplacement des deux catet catsen une seule fois:

'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
Elias Van Ootegem
la source
Je pense que la partie intéressante supplémentaire devrait être placée en bas. ps.: Je viens de remarquer que la moitié de la première ligne est hors de la zone, permettez-moi de corriger cela!
69

Correspondance avec une expression régulière globale:

anotherString = someString.replace(/cat/g, 'dog');
scronide
la source
60

Pour remplacer une utilisation unique:

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

Pour remplacer plusieurs fois, utilisez:

var res = str.replace(/abc/g, "");
Indrajeet Singh
la source
pour quelqu'un doit remplacer \ n, vous pouvez le faire comme:replace(/\n/g, '<br/>')
Phan Van Linh
58

Ce sont les méthodes les plus courantes et les plus lisibles.

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

Méthode 1:

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

Méthode 2:

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

Méthode 3:

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

Méthode 4:

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

Production:

console.log(str);
// Test replaced text test test replaced text test test test replaced text test test replaced text
Adnan Toky
la source
44
str = str.replace(/abc/g, '');

Ou essayez la fonction replaceAll à partir d'ici:

Quelles sont les méthodes JavaScript utiles qui étendent les objets intégrés?

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

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

EDIT: Clarification sur le remplacementToute disponibilité

La méthode 'replaceAll' est ajoutée au prototype de String. Cela signifie qu'il sera disponible pour tous les objets chaîne / littéraux.

Par exemple

var output = "test this".replaceAll('this', 'that');  //output is 'test that'.
output = output.replaceAll('that', 'this'); //output is 'test this'
SolutionYogi
la source
2
Pouvez-vous réécrire la fonction replaceAll () pour ceux qui n'utilisent pas de prototype?
Cliquez sur Upvote
@Click Upvote .... vous utilisez un prototype, il fait partie de tous les objets JS. Je pense que vous pensez à prototype.js la bibliothèque JS.
seth
seth, une petite correction. Si vous ajoutez une méthode à un prototype, elle est disponible pour tous les objets de ce type. La méthode replceAll a été ajoutée au prototype String et devrait fonctionner pour tous les objets chaîne.
SolutionYogi
@solutionyogi - Oui, j'ai déjà utilisé un prototype (correctement). J'étais juste en train de répondre au commentaire du PO à propos de "ne pas utiliser de prototype" que je supposais signifier Prototype.js (peut-être incorrectement?). J'aurais dû dire "un prototype" car j'essayais de dire que les objets JavaScript ont un prototype. Ainsi, le PO «utilisait déjà un prototype», quoique de manière «indirecte». Indirecte pourrait être le mauvais terme à utiliser ici, mais je suis fatigué alors mea culpa.
seth
41

Utiliser RegExpen JavaScript pourrait faire le travail pour vous, faites simplement quelque chose comme le code ci-dessous, n'oubliez pas ce /gqui se démarque pour global :

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

Si vous pensez à réutiliser, créez une fonction pour le faire pour vous, mais ce n'est pas recommandé car ce n'est qu'une fonction de ligne, mais encore une fois si vous l'utilisez fortement, vous pouvez écrire quelque chose comme ceci:

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

et utilisez-le simplement dans votre code encore et encore comme ci-dessous:

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

Mais comme je l'ai mentionné plus tôt, cela ne fera pas une énorme différence en termes de lignes à écrire ou de performances, seule la mise en cache de la fonction peut affecter des performances plus rapides sur les longues chaînes et également une bonne pratique du code DRY si vous souhaitez réutiliser.

Alireza
la source
40

Supposons que vous souhaitiez remplacer tous les 'abc' par '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

J'essayais de penser à quelque chose de plus simple que de modifier le prototype de chaîne.

Emilio Grisolía
la source
1
Simple, facile et probablement l'option la plus performante: belle réponse.
machineghost
En fait, même si je ne l'ai pas métrique personnellement, le fractionnement / jointure est généralement une solution très performante.
machineghost
1
c'est même en chrome, 100% plus rapide sur firefox, et 50% plus lent sur IE ...: jsperf.com/replace-regex-split-join
Olivier
37

Utilisez une expression régulière:

str.replace(/abc/g, '');
Donnie DeBoer
la source
32

Remplacement des guillemets simples:

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

    return text;
}
Chris Rosete
la source
2
Comment puis-je changer la deuxième ligne pour remplacer les chaînes? Cela ne fonctionne pas: text = text.replace ('hey', 'hello'); Une idée?
Stefan Đorđević
2
Bien sûr Stefan, voici le code ... text = text.replace (/ hey / g, 'hello');
Chris Rosete
26

// boucle jusqu'à ce que le nombre d'occurrences atteigne 0. OU simplement copier / coller

    function replaceAll(find, replace, str) 
    {
      while( str.indexOf(find) > -1)
      {
        str = str.replace(find, replace);
      }
      return str;
    }
Raseela
la source
23
Cette méthode est dangereuse, ne l'utilisez pas. Si la chaîne de remplacement contient le mot-clé de recherche, une boucle infinie se produira. À tout le moins, stockez le résultat de .indexOfdans une variable et utilisez cette variable comme deuxième paramètre de .indexOf(moins la longueur du mot-clé, plus la longueur de la chaîne de remplacement).
Rob W
Je pense d'abord à remplacer le modèle de recherche par un caractère unicode weired, nous sommes sûrs qu'il n'est pas utilisé dans la chaîne d'entrée. Comme U + E000 dans l'espace privé. Et puis replacez-le sur la cible. J'ai construit ça ici. . Je ne sais pas si c'est une bonne idée.
Lux
26
str = str.replace(new RegExp("abc", 'g'), "");

a mieux fonctionné pour moi que les réponses ci-dessus. new RegExp("abc", 'g')crée donc un RegExp qui correspond à toutes les occurrences ( 'g'flag) du texte ( "abc"). La deuxième partie est ce qui est remplacé, dans votre cas, une chaîne vide ( ""). strest la chaîne, et nous devons la remplacer, car replace(...)renvoie simplement le résultat, mais pas les substitutions. Dans certains cas, vous voudrez peut-être l'utiliser.

csomakk
la source
Bien que cet extrait de code puisse être la solution, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
yivi
Oui vous avez raison. ajoutée. l'a également édité pour répondre à la question d'origine :)
csomakk
Remarque: le drapeau g dans l'expression régulière signifie que c'est un drapeau global qui correspondra à toutes les occurrences
commentaire posté le
25

Il s'agit de la version la plus rapide qui n'utilise pas d'expressions régulières .

Jsperf révisé

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

Il est presque deux fois plus rapide que la méthode de fractionnement et de jointure.

Comme indiqué dans un commentaire ici, cela ne fonctionnera pas si votre omitvariable contient place, comme dans:, replaceAll("string", "s", "ss")car elle pourra toujours remplacer une autre occurrence du mot.

Il y a un autre jsperf avec des variantes sur mon remplacement récursif qui vont encore plus vite ( http://jsperf.com/replace-all-vs-split-join/12 )!

  • Mise à jour du 27 juillet 2017: il semble que RegExp ait désormais les performances les plus rapides du Chrome 59 récemment sorti.
Cole Lawrence
la source
J'ai adoré votre solution ... J'aimerais pouvoir vous donner +10 mais voici mon +1. Je pense que vous pouvez stocker l'index de la sous-chaîne qui a été remplacée et passer à la suivante si une correspondance est trouvée à un index inférieur pour éviter ce problème de boucle infinie. Je ne peux pas commenter la performance parce que je ne l'ai pas testée mais c'est juste mes 2 cents sur cette pièce d'excellence.
Fr0zenFyr
@ fr0zenfyr si vous voulez vérifier si l'omission est en place (pour éviter une boucle infinie), vous pouvez faire une conditionnelle comme if(place.replace(omit) === omit) {Aucune correspondance, il est donc sûr d'utiliser remplacer la boucle } else {Correspondance, utilisez donc une méthode différente comme le fractionnement et la jointure}
Cole Lawrence
Hmm .. mais quel est l'intérêt de combiner deux solutions? De toute façon, je ne suis pas fan de l'approche split / join .. merci pour le conseil ..
Fr0zenFyr
@ Fr0zenFyr Je crois que le but de combiner les deux solutions serait de recourir à une méthode plus lente si vous ne pouvez pas utiliser la plus rapide (lorsque la boucle serait infinie par exemple). Ce serait donc un garde-fou pour assurer la fonctionnalité avec efficacité, mais sans possibilité de défaillance.
Cole Lawrence
@momomo comment imparfait?
SandRock
24

Performance

Aujourd'hui 27.12.2019 j'effectue des tests sur macOS v10.13.6 (High Sierra) pour les solutions choisies.

Conclusions

  • Le str.replace(/abc/g, '');( C ) est une bonne solution rapide multi-navigateur pour toutes les chaînes.
  • Les solutions basées sur split-join( A, B ) ou replace( C, D ) sont rapides
  • Les solutions basées sur while( E, F, G, H ) sont lentes - généralement ~ 4 fois plus lentes pour les petites cordes et environ ~ 3000 fois (!) Plus lentes pour les longues cordes
  • Les solutions de récurrence ( RA, RB ) sont lentes et ne fonctionnent pas pour les longues chaînes

Je crée également ma propre solution. Il semble que ce soit actuellement le plus court qui fasse le travail de question:

str.split`abc`.join``

Détails

Les tests ont été effectués sur Chrome 79.0, Safari 13.0.4 et Firefox 71.0 (64 bits). Les tests RAet l' RButilisation de la récursivité. Résultats

Entrez la description de l'image ici

Chaîne courte - 55 caractères

Vous pouvez exécuter des tests sur votre machine ICI . Résultats pour Chrome:

Entrez la description de l'image ici

Chaîne longue: 275 000 caractères

Les solutions récursives RA et RB donnent

RangeError: dépassement de la taille maximale de la pile d'appels

Pour 1 million de personnages, ils cassent même Chrome

entrez la description de l'image ici

J'essaie d'effectuer des tests pour 1M de caractères pour d'autres solutions, mais E, F, G, H prennent tellement de temps que le navigateur me demande de casser le script, donc je réduit la chaîne de test à 275K caractères. Vous pouvez exécuter des tests sur votre machine ICI . Résultats pour Chrome

entrez la description de l'image ici

Code utilisé dans les tests

Kamil Kiełczewski
la source
1
Maintenant, c'est une sacrée réponse en profondeur! Merci beaucoup! Cependant, ce qui m'intéresse, c'est pourquoi la syntaxe du "nouveau RegExp (...)" apporte autant d'amélioration.
Márk Gergely Dolinka
21

Si ce que vous voulez trouver est déjà dans une chaîne et que vous n'avez pas d'escape regex à portée de main, vous pouvez utiliser 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'));

rakslice
la source
Merci! Cette solution fonctionne parfaitement pour mon problème :)
xero399
19
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;
}
Tim Rivoli
la source
Je me demande à quel point cela fonctionne ... la sous-chaîne est native ou parcourt le tableau de caractères pour créer les nouveaux personnages.
mmm
16

J'aime cette méthode (elle a l'air un peu plus propre):

text = text.replace(new RegExp("cat","g"), "dog"); 
Owen
la source
1
D'accord, comment échappez-vous à la chaîne pour l'utiliser comme modèle d'expression régulière?
rakslice
Je ne le fais pas, je l'utilise juste pour du texte brut
Owen
15

Le moyen le plus simple de le faire sans utiliser aucune expression régulière est de fractionner et de rejoindre comme le code ici:

var str = "Test abc test test abc test test test abc test test abc";
str.split('abc').join('')
sajadre
la source
13
var str = "ff ff f f a de def";
str = str.replace(/f/g,'');
alert(str);

http://jsfiddle.net/ANHR9/

pkdkk
la source
quel était l'intérêt d'un violon qui ne contient que le même javascript
JGallardo
13
while (str.indexOf('abc') !== -1)
{
    str = str.replace('abc', '');
}
zdennis
la source
13

Si la chaîne contient un modèle similaire abccc, vous pouvez utiliser ceci:

str.replace(/abc(\s|$)/g, "")
mostafa elmadany
la source
13

Les réponses précédentes sont beaucoup trop compliquées. Utilisez simplement la fonction de remplacement comme ceci:

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

Exemple:

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

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

console.log(res);

Noir
la source
10

Si vous essayez de vous assurer que la chaîne que vous recherchez n'existera pas même après le remplacement, vous devez utiliser une boucle.

Par exemple:

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

Une fois terminé, vous aurez toujours «test abc»!

La boucle la plus simple pour résoudre ce problème serait:

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

Mais cela exécute le remplacement deux fois pour chaque cycle. Peut-être (au risque d'être rejeté) qui peut être combiné pour une forme légèrement plus efficace mais moins lisible:

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

Cela peut être particulièrement utile lorsque vous recherchez des chaînes en double.
Par exemple, si nous avons «a ,,, b» et que nous souhaitons supprimer toutes les virgules en double.
[Dans ce cas, on pourrait faire .replace (/, + / g, ','), mais à un moment donné, l'expression régulière devient complexe et suffisamment lente pour boucler à la place.]

SamGoody
la source
10

Bien que les gens aient mentionné l'utilisation de l'expression rationnelle, il existe une meilleure approche si vous souhaitez remplacer le texte indépendamment de la casse du texte. Comme majuscule ou minuscule. Utilisez la syntaxe ci-dessous

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

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

Vous pouvez vous référer à l'exemple détaillé ici .

Code Cheezy
la source
à partir du site d'exemple: "/ toBeReplacedString / gi est l'expression régulière que vous devez utiliser. Ici g représente la correspondance globale et i représente la casse. Par défaut, l'expression
régulière
8

Vous pouvez simplement utiliser la méthode ci-dessous

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

Ajoutez simplement /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 signifie global

Reza Fahmi
la source