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


J'ai cette chaîne:

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

Faire

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

semble seulement supprimer la première occurrence de abc dans la chaîne ci-dessus. Comment puis-je remplacer tout occurrences de celui-ci?


3164
2017-07-17 17:53


origine


Réponses:


Par souci d'exhaustivité, j'ai réfléchi à la méthode que je devrais utiliser pour faire cela. Il y a essentiellement deux façons de faire cela comme suggéré par les autres réponses sur 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 en tant qu'extensions sur le prototype String simplement à des fins d'illustration, montrant différentes implémentations d'une méthode standard hypothétique sur le String prototype 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);
};

Diviser et joindre (fonctionnel) Implémentation

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 dans les coulisses en termes d'efficacité, j'ai eu tendance à pencher vers la scission et à rejoindre la mise en œuvre dans le passé sans penser à la performance. Quand je me suis demandé ce qui était le plus efficace, et par quelle marge, je l'ai utilisé comme une excuse pour le savoir.

Sur ma machine Windows 8 Chrome, l'implémentation basée sur l'expression régulière est la plus rapide, avec le diviser et rejoindre la mise en œuvre étant 53% plus lent. Ce qui signifie que les expressions régulières sont deux fois plus rapides pour l'entrée lorem ipsum que j'ai utilisée.

Regarde ça référence exécuter ces deux implémentations les unes contre les autres.


Comme indiqué dans le commentaire ci-dessous par @ Thomasheduc et d'autres, il pourrait y avoir un problème avec l'implémentation basée sur l'expression régulière si search contient certains caractères qui sont réservés caractères spéciaux dans les expressions régulières. L'implémentation suppose que l'appelant va au préalable échapper à la chaîne ou ne transmettra que les chaînes sans les caractères de la table Expressions régulières (MDN).

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

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

Nous pourrions appeler escapeRegExp au sein de notre String.prototype.replaceAll Cependant, je ne sais pas dans quelle mesure cela affectera les performances (potentiellement même pour des chaînes pour lesquelles l'échappement n'est pas nécessaire, comme toutes les chaînes alphanumériques).


1627
2017-07-12 01:46



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

En réponse à un commentaire:

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

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

En réponse à Cliquez sur Upvotele commentaire, vous pourriez 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 spéciaux (méta), et en tant que tels, il est dangereux de passer aveuglément un argument dans le find fonctionner ci-dessus sans le pré-traiter pour échapper à ces caractères. Ceci est couvert dans le Réseau de développeurs Mozillade Guide JavaScript sur les expressions régulières, où ils présentent la fonction d'utilité suivante:

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

Donc, pour faire le replaceAll() fonction ci-dessus plus sûr, il pourrait être modifié à la suivante si vous incluez également escapeRegExp:

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

3586
2017-07-17 17:54



Note: Ne l'utilisez pas en code réel.

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 modèle général est

str.split(search).join(replacement)

Dans certains cas, cela était plus rapide que replaceAll et une expression régulière, mais cela ne semble plus être le cas dans les navigateurs modernes. Donc, cela ne devrait vraiment être utilisé comme un hack rapide pour éviter d'avoir besoin d'échapper à l'expression régulière, pas en code réel.


1193
2017-07-17 20:29



Utiliser une expression régulière avec le g Le jeu de drapeau 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


505
2018-05-06 23:18



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

MODIFIER 

Si ton find contiendra des caractères spéciaux, alors vous devez leur é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/


90
2018-02-11 23:03



Mettre à jour:

C'est un peu tard pour une mise à jour, mais depuis que je suis tombé sur cette question, j'ai remarqué que ma réponse précédente n'en est pas une. Puisque la question impliquait de remplacer un seul mot, il est incroyable que personne n'ait pensé à utiliser des limites de mots (\b)

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

C'est une regex 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. Ainsi, les conditions peuvent être utilisées dans ce cas pour éviter de remplacer les 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"

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

@Mike, cochez la réponse que j'ai donnée ici ... regexp n'est pas le seul moyen de remplacer plusieurs occurrences d'un subsrting, 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 mot - que la réponse approuvée fera, aussi! Vous pouvez contourner ce problème en utilisant des expressions régulières qui, je le reconnais, sont un peu plus complexes et, par conséquent, un peu plus lentes:

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 que c'est, alors? IMHO, une regex qui remplace seulement «chat» conditionnellement. (c'est-à-dire ne fait 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"

Ma conjecture est, cela répond à vos besoins. Ce n'est pas complètement étanche, bien sûr, mais cela devrait suffire pour vous aider à démarrer. Je vous recommande de lire 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


Dernier ajout:

Étant donné que cette question reçoit encore beaucoup de points de vue, j'ai pensé que je pourrais ajouter un exemple de .replace utilisé avec une fonction de rappel. Dans ce cas, il simplifie considérablement l'expression et offre encore plus de flexibilité, comme le remplacement avec une capitalisation correcte ou le remplacement des deux cat et cats en une 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

75
2018-03-01 10:02



Correspondance avec une expression régulière globale:

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

45
2018-05-06 23:23