JavaScript sostituire / regex


113

Data questa funzione:

function Repeater(template) {

    var repeater = {

        markup: template,

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

    };

    return repeater;

};

Come faccio a this.markup.replace()sostituire globalmente? Ecco il problema. Se lo uso in questo modo:

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

Il valore dell'avviso è "foobar $ TEST_ONE".

Se cambio Repeaterin quanto segue, non viene sostituito nulla in Chrome:

function Repeater(template) {

    var repeater = {

        markup: template,

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

    };

    return repeater;

};

... e l'avviso è $TEST_ONE $TEST_ONE.

Risposte:


147

È necessario eseguire l'escape doppia di qualsiasi carattere RegExp (una volta per la barra nella stringa e una volta per la regexp):

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

Altrimenti, cerca la fine della riga e "TESTONE" (che non trova mai).

Personalmente, non sono un grande fan della creazione di regexp usando le stringhe per questo motivo. Il livello di fuga necessario potrebbe portarti a bere. Sono sicuro che gli altri si sentono in modo diverso però e amano bere quando scrivono regex.


Ma replace () riceve la regex come variabile.
nucleo

8
@ Chris - Non penso che faccia differenza se usi /pattern/o new RegExp("pattern").
harto

@seth, la tua risposta funziona, ma non fornisce una soluzione al codice da OP. Come devo chiamare il codice di OP?
Black

82

In termini di interpretazione del modello, non c'è differenza tra le seguenti forme:

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

Se vuoi sostituire una stringa letterale usando il replacemetodo, penso che puoi semplicemente passare una stringa invece di un'espressione regolare a replace.

Altrimenti, dovresti prima eseguire l'escape di tutti i caratteri speciali regexp nel pattern, forse in questo modo:

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

// ...

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

12
Non sapevo prima, che / pattern / è lo stesso del nuovo RegExp ("pattern"). Davvero aiutato!
Nik Sumeiko

1
Qualche motivo per non utilizzare una whitelist invece di una blacklist? ad esempio: s.replace (/ (\ W) / g, '\\ $ 1')
greg.kindel

1
La prima forma elencata è migliore. È buona norma evitare la nuova parola chiave.
Druska

2
Non è corretto affermare che l'espressione regolare letterale (/ regex /) è la stessa di RegExp ("regex"). Nell'espressione regolare letterale, il solidus inverso ('\') non ha bisogno di essere preceduto da caratteri di escape ('\\') affinché faccia parte dell'espressione regolare. Inoltre, il valore letterale dell'espressione regolare può essere compilato quando lo script viene analizzato piuttosto che ogni volta che viene eseguita la funzione. Per abbinare un solidus inverso puoi scrivere / \\ / o RexExp ("\\\\").
John

31

Il tuo pattern regex dovrebbe avere il modificatore g:

var pattern = /[somepattern]+/g;

notare la g alla fine. dice al sostituto di fare una sostituzione globale.

Inoltre non è necessario utilizzare l'oggetto RegExp, è possibile costruire il modello come sopra. Pattern di esempio:

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

un modello è sempre circondato da / su entrambi i lati - con i modificatori dopo la / finale, il modificatore g è il globale.

EDIT: Perché è importante se il pattern è una variabile? Nel tuo caso funzionerebbe in questo modo (nota che il pattern è ancora una variabile):

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

Ma dovresti cambiare la tua funzione di sostituzione in questo:

this.markup = this.markup.replace(pattern, value);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.