JavaScript remplacer / regex


113

Compte tenu de cette fonction:

function Repeater(template) {

    var repeater = {

        markup: template,

        replace: function(pattern, value) {
            this.markup = this.markup.replace(pattern, value);
        }

    };

    return repeater;

};

Comment faire this.markup.replace()remplacer globalement? Voici le problème. Si je l'utilise comme ça:

alert(new Repeater("$TEST_ONE $TEST_ONE").replace("$TEST_ONE", "foobar").markup);

La valeur de l'alerte est "foobar $ TEST_ONE".

Si je change Repeatercomme suit, rien n'est remplacé dans Chrome:

function Repeater(template) {

    var repeater = {

        markup: template,

        replace: function(pattern, value) {
            this.markup = this.markup.replace(new RegExp(pattern, "gm"), value);
        }

    };

    return repeater;

};

... et l'alerte est $TEST_ONE $TEST_ONE.

Réponses:


147

Vous devez double échapper tous les caractères RegExp (une fois pour la barre oblique dans la chaîne et une fois pour l'expression rationnelle):

  "$TESTONE $TESTONE".replace( new RegExp("\\$TESTONE","gm"),"foo")

Sinon, il recherche la fin de la ligne et «TESTONE» (qu'il ne trouve jamais).

Personnellement, je ne suis pas un grand fan de la création d'expressions rationnelles en utilisant des chaînes pour cette raison. Le niveau d'évasion nécessaire pourrait vous amener à boire. Je suis sûr que les autres se sentent différemment et aiment boire lorsqu'ils écrivent des expressions régulières.


Mais replace () reçoit l'expression rationnelle comme une variable.
core

8
@Chris - Je ne pense pas que cela fasse une différence si vous utilisez /pattern/ou new RegExp("pattern").
harto

@seth, votre réponse fonctionne, mais elle ne fournit pas de solution au code d'OP. Comment dois-je appeler le code OP?
Black

82

En termes d'interprétation des modèles, il n'y a aucune différence entre les formes suivantes:

  • /pattern/
  • new RegExp("pattern")

Si vous souhaitez remplacer une chaîne littérale en utilisant la replaceméthode, je pense que vous pouvez simplement passer une chaîne au lieu d'une expression rationnelle à replace.

Sinon, vous devrez d'abord échapper tous les caractères spéciaux de l'expression rationnelle dans le modèle - peut-être comme ceci:

function reEscape(s) {
    return s.replace(/([.*+?^$|(){}\[\]])/mg, "\\$1");
}

// ...

var re = new RegExp(reEscape(pattern), "mg");
this.markup = this.markup.replace(re, value);

12
Je ne savais pas avant, que / pattern / est identique au nouveau RegExp ("pattern"). Vraiment aidé!
Nik Sumeiko

1
Une raison pour ne pas utiliser une liste blanche au lieu d'une liste noire? par exemple: s.replace (/ (\ W) / g, '\\ $ 1')
greg.kindel

1
La première forme répertoriée est meilleure. Il est recommandé d'éviter le nouveau mot-clé.
Druska

2
Il n'est pas exact de dire que le littéral d'expression régulière (/ regex /) est le même que RegExp ("regex"). Dans le littéral d'expression régulière, le solidus inversé ('\') n'a pas besoin d'être lui-même échappé ('\\') pour qu'il fasse partie de l'expression régulière. En outre, le littéral d'expression régulière peut être compilé lorsque le script est analysé plutôt qu'à chaque fois que la fonction est exécutée. Pour faire correspondre un solidus inversé, vous pouvez écrire / \\ / ou RexExp ("\\\\").
John

31

Votre modèle regex doit avoir le modificateur g:

var pattern = /[somepattern]+/g;

remarquez le g à la fin. il indique au remplaçant d'effectuer un remplacement global.

De plus, vous n'avez pas besoin d'utiliser l'objet RegExp, vous pouvez construire votre modèle comme ci-dessus. Exemple de modèle:

var pattern = /[0-9a-zA-Z]+/g;

un motif est toujours entouré par / de chaque côté - avec des modificateurs après le / final, le modificateur g étant le global.

EDIT: Pourquoi est-ce important si le motif est une variable? Dans votre cas, cela fonctionnerait comme ceci (notez que le modèle est toujours une variable):

var pattern = /[0-9a-zA-Z]+/g;
repeater.replace(pattern, "1234abc");

Mais vous devrez changer votre fonction de remplacement en ceci:

this.markup = this.markup.replace(pattern, value);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.