JavaScript ersetzen / Regex

113

Angesichts dieser Funktion:

function Repeater(template) {

    var repeater = {

        markup: template,

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

    };

    return repeater;

};

Wie kann ich this.markup.replace()global ersetzen? Hier ist das Problem. Wenn ich es so benutze:

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

Der Wert der Warnung lautet "foobar $ TEST_ONE".

Wenn ich Repeaterzu Folgendem wechsle , wird in Chrome nichts ersetzt:

function Repeater(template) {

    var repeater = {

        markup: template,

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

    };

    return repeater;

};

... und der Alarm ist $TEST_ONE $TEST_ONE.

Ader
quelle

Antworten:

147

Sie müssen alle RegExp-Zeichen doppelt maskieren (einmal für den Schrägstrich in der Zeichenfolge und einmal für den regulären Ausdruck):

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

Andernfalls sucht es nach dem Ende der Zeile und nach 'TESTONE' (das es nie findet).

Persönlich bin ich aus diesem Grund kein großer Fan davon, reguläre Ausdrücke mit Strings zu erstellen. Das Ausmaß der Flucht, das benötigt wird, könnte Sie zum Trinken führen. Ich bin mir sicher, dass andere sich anders fühlen und gerne trinken, wenn sie Regexes schreiben.

Seth
quelle
Ersetzen () erhält jedoch den regulären Ausdruck als Variable.
Kern
8
@ Chris - Ich glaube nicht, dass es einen Unterschied macht, ob Sie /pattern/oder verwenden new RegExp("pattern").
Harto
@seth, Ihre Antwort funktioniert, bietet jedoch keine Lösung für den Code von OP. Wie muss ich den OP-Code aufrufen?
Schwarz
82

In Bezug auf die Musterinterpretation gibt es keinen Unterschied zwischen den folgenden Formen:

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

Wenn Sie replaceeine Literalzeichenfolge mit der Methode ersetzen möchten, können Sie meiner Meinung nach einfach eine Zeichenfolge anstelle eines regulären Ausdrucks an übergeben replace.

Andernfalls müssten Sie zuerst alle regulären Ausdruckszeichen im Muster maskieren - vielleicht so:

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

// ...

var re = new RegExp(reEscape(pattern), "mg");
this.markup = this.markup.replace(re, value);
Harto
quelle
12
Wusste vorher nicht, dass / pattern / dasselbe ist wie neues RegExp ("pattern"). Wirklich geholfen!
Nik Sumeiko
1
Gibt es einen Grund, keine Whitelist anstelle einer Blacklist zu verwenden? zB: s.replace (/ (\ W) / g, '\\ $ 1')
greg.kindel
1
Das erste aufgeführte Formular ist besser. Es wird empfohlen, das neue Schlüsselwort zu vermeiden .
Druska
2
Es ist nicht richtig zu sagen, dass das Literal für reguläre Ausdrücke (/ regex /) dasselbe ist wie RegExp ("regex"). Im Literal des regulären Ausdrucks muss der umgekehrte Solidus ('\') nicht selbst maskiert werden ('\\'), damit er Teil des regulären Ausdrucks ist. Darüber hinaus kann das Literal für reguläre Ausdrücke kompiliert werden, wenn das Skript analysiert wird, und nicht jedes Mal, wenn die Funktion ausgeführt wird. Um einem Reverse-Solidus zu entsprechen, können Sie entweder / \\ / oder RexExp ("\\\\") schreiben.
John
31

Ihr Regex-Muster sollte den Modifikator g haben:

var pattern = /[somepattern]+/g;

Beachten Sie das g am Ende. Es weist den Ersetzer an, einen globalen Ersatz durchzuführen.

Außerdem müssen Sie das RegExp-Objekt nicht verwenden. Sie können Ihr Muster wie oben erstellen. Beispielmuster:

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

Ein Muster ist immer von / auf beiden Seiten umgeben - mit Modifikatoren nach dem letzten /, wobei der Modifikator g der globale ist.

EDIT: Warum ist es wichtig, wenn Muster eine Variable ist? In Ihrem Fall würde es so funktionieren (beachten Sie, dass das Muster immer noch eine Variable ist):

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

Sie müssten jedoch Ihre Ersetzungsfunktion folgendermaßen ändern:

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