JavaScript reemplazar / regex

113

Dada esta función:

function Repeater(template) {

    var repeater = {

        markup: template,

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

    };

    return repeater;

};

¿Cómo hago para this.markup.replace()reemplazar globalmente? Aquí está el problema. Si lo uso así:

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

El valor de la alerta es "foobar $ TEST_ONE".

Si cambio Repeatera lo siguiente, no se reemplaza nada en Chrome:

function Repeater(template) {

    var repeater = {

        markup: template,

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

    };

    return repeater;

};

... y la alerta es $TEST_ONE $TEST_ONE.

núcleo
fuente

Respuestas:

147

Necesita doble escape de cualquier carácter RegExp (una vez para la barra en la cadena y una vez para la expresión regular):

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

De lo contrario, busca el final de la línea y 'TESTONE' (que nunca encuentra).

Personalmente, no soy un gran fan de la construcción de expresiones regulares usando cadenas por esta razón. El nivel de escape que se necesita podría llevarlo a beber. Estoy seguro de que los demás se sienten de manera diferente y les gusta beber cuando escriben expresiones regulares.

seth
fuente
Pero replace () recibe la expresión regular como una variable.
core
8
@Chris: no creo que haya diferencia si usas /pattern/o new RegExp("pattern").
harto
@seth, su respuesta funciona, pero no proporciona una solución al código de OP. ¿Cómo tengo que llamar al código de OP?
Negro
82

En términos de interpretación de patrones, no hay diferencia entre las siguientes formas:

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

Si desea reemplazar una cadena literal usando el replacemétodo, creo que puede pasar una cadena en lugar de una expresión regular a replace.

De lo contrario, primero tendría que escapar de los caracteres especiales de expresiones regulares en el patrón, tal vez así:

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

// ...

var re = new RegExp(reEscape(pattern), "mg");
this.markup = this.markup.replace(re, value);
harto
fuente
12
No sabía antes, que / patrón / es lo mismo que la nueva expresión regular ("patrón"). ¡Realmente ayudó!
Nik Sumeiko
1
¿Alguna razón para no usar una lista blanca en lugar de una lista negra? por ejemplo: s.replace (/ (\ W) / g, '\\ $ 1')
greg.kindel
1
La primera forma de la lista es mejor. Es una buena práctica evitar la nueva palabra clave.
Druska
2
No es exacto decir que la expresión regular literal (/ regex /) es la misma que RegExp ("regex"). En el literal de expresión regular, el reverse-solidus ('\') no necesita escaparse ('\\') para que sea parte de la expresión regular. Además, el literal de expresión regular se puede compilar cuando se analiza el script en lugar de cada vez que se ejecuta la función. Para hacer coincidir un solidus inverso, puede escribir / \\ / o RexExp ("\\\\").
John
31

Su patrón de expresiones regulares debe tener el modificador g:

var pattern = /[somepattern]+/g;

observe la g al final. le dice al reemplazador que haga un reemplazo global.

Además, no necesita usar el objeto RegExp, puede construir su patrón como se indica arriba. Patrón de ejemplo:

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

un patrón siempre está rodeado por / a cada lado, con modificadores después del / final, siendo el modificador g el global.

EDITAR: ¿Por qué importa si el patrón es una variable? En su caso, funcionaría así (observe que el patrón sigue siendo una variable):

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

Pero necesitaría cambiar su función de reemplazo a esto:

this.markup = this.markup.replace(pattern, value);
Darko Z
fuente