2009-07-22 4 views
72

Compte tenu de cette fonction:remplacer JavaScript/regex

function Repeater(template) { 

    var repeater = { 

     markup: template, 

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

    }; 

    return repeater; 

}; 

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

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

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

Si je change Repeater à ce qui suit, alors rien dans 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épondre

102

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

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

Sinon, il recherche la fin de la ligne et « testone » (qui il ne trouve jamais).

Personnellement, je ne suis pas un grand fan de construction de regexp utilisant des chaînes pour cette raison. Le niveau d'évasion nécessaire peut vous amener à boire. Je suis sûr que les autres se sentent différemment et aiment boire quand on écrit des expressions rationnelles.

+0

Mais remplacer() Reçoit la regex comme variable. – core

+0

Correction mineure - '$' indique une fin de ligne dans une expression rationnelle. – harto

+6

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

21

Votre modèle regex doit avoir le modificateur g:

var pattern = /[somepattern]+/g; 

avis du g à la fin. il indique au remplaçant de faire un remplacement global.

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

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

un motif est toujours entourée par/de chaque côté - avec des modificateurs après le dernier /, le modificateur de g étant l'échelle mondiale.

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

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

Mais vous devez changer votre fonction de remplacement à ceci:

this.markup = this.markup.replace(pattern, value); 
55

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

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

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

Sinon, vous auriez à échapper à des caractères spéciaux regexp dans le premier motif - 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); 
+9

Je ne savais pas avant, que/pattern/est le même que new RegExp ("pattern"). Vraiment aidé! –

+1

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

+1

Le premier formulaire répertorié est meilleur. Il est recommandé d'éviter le mot-clé _new_. – Druska