it-swarm.com.de

Gibt es eine RegExp.escape-Funktion in Javascript?

Ich möchte nur einen regulären Ausdruck aus einer möglichen Zeichenfolge erstellen.

var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);

Gibt es eine eingebaute Methode dafür? Wenn nicht, was benutzen die Leute? Ruby hat RegExp.escape . Ich habe nicht das Gefühl, dass ich mein eigenes schreiben müsste, da draußen muss es einen Standard geben. Vielen Dank!

385
Lance Pollard

Die oben verlinkte Funktion ist unzureichend. Es kann nicht entkommen ^ oder $ (Anfang und Ende der Zeichenfolge) oder -, der in einer Zeichengruppe für Bereiche verwendet wird.

Verwenden Sie diese Funktion:

RegExp.escape= function(s) {
    return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};

Während es auf den ersten Blick unnötig erscheinen mag, - (ebenso gut wie ^) macht die Funktion für das Einfügen von Escapezeichen in eine Zeichenklasse sowie für den Textkörper der Regex geeignet.

Flucht / macht die Funktion zur Verwendung in einem JS-Regex-Literal für spätere Auswertungen geeignet.

Da es keinen Nachteil gibt, einem von beiden zu entkommen, ist es sinnvoll, zu entkommen, um breitere Anwendungsfälle abzudecken.

Und ja, es ist ein enttäuschender Fehler, dass dies nicht Teil des Standard-JavaScript ist.

503
bobince

Für alle, die lodash benutzen, ist seit v3.0. eine _. EscapeRegExp Funktion eingebaut:

_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'

Und für den Fall, dass Sie nicht die vollständige Lodash-Bibliothek benötigen, benötigen Sie möglicherweise nur diese Funktion !

91
gustavohenke

Die meisten Ausdrücke hier lösen einzelne spezifische Anwendungsfälle.

Das ist okay, aber ich bevorzuge einen "Always Works" -Ansatz.

function regExpEscape(literal_string) {
    return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}

Dadurch wird eine Literalzeichenfolge für eine der folgenden Verwendungen in regulären Ausdrücken "vollständig" maskiert:

  • Einfügen in einen regulären Ausdruck. Z.B. new RegExp(regExpEscape(str))
  • Einfügen in eine Zeichenklasse. Z.B. new RegExp('[' + regExpEscape(str) + ']')
  • Einfügen in den Integer Count-Bezeichner. Z.B. new RegExp('x{1,' + regExpEscape(str) + '}')
  • Ausführung in Nicht-JavaScript-Modulen für reguläre Ausdrücke.

Abgedeckte Sonderzeichen:

  • -: Erstellt einen Zeichenbereich in einer Zeichenklasse.
  • [/]: Startet/beendet eine Zeichenklasse.
  • {/}: Startet/beendet einen Nummernbezeichner.
  • (/): Startet/beendet eine Gruppe.
  • */+/?: Gibt den Wiederholungstyp an.
  • .: Entspricht einem beliebigen Zeichen.
  • \: Maskiert Zeichen und startet Entities.
  • ^: Gibt den Beginn der Übereinstimmungszone an und negiert die Übereinstimmung in einer Zeichenklasse.
  • $: Gibt das Ende der übereinstimmenden Zone an.
  • |: Gibt den Wechsel an.
  • #: Gibt einen Kommentar im Modus mit freiem Abstand an.
  • \s: Wird im Modus für freie Abstände ignoriert.
  • ,: Trennt die Werte im Nummernbezeichner.
  • /: Startet oder beendet den Ausdruck.
  • :: Vervollständigt spezielle Gruppentypen und Teile von Zeichenklassen im Perl-Stil.
  • !: Negiert die Gruppe mit der Breite Null.
  • </=: Teil der Gruppenspezifikationen mit der Breite Null.

Anmerkungen:

  • / Ist für reguläre Ausdrücke nicht unbedingt erforderlich. Es schützt jedoch für den Fall, dass jemand (schaudert)eval("/" + pattern + "/"); ausführt.
  • , Stellt sicher, dass, wenn die Zeichenfolge im numerischen Bezeichner eine Ganzzahl sein soll, ein RegExp-Kompilierungsfehler verursacht wird, anstatt im Hintergrund eine falsche Kompilierung durchzuführen.
  • # Und \s Müssen nicht in JavaScript maskiert werden, sondern in vielen anderen Varianten. Sie werden hier ausgeblendet, falls der reguläre Ausdruck später an ein anderes Programm übergeben wird.

Wenn Sie den regulären Ausdruck auch gegen mögliche Ergänzungen der Funktionen der JavaScript-Regex-Engine zukunftssicher machen müssen, empfehle ich die Verwendung der paranoideren Methode:

function regExpEscapeFuture(literal_string) {
    return literal_string.replace(/[^A-Za-z0-9_]/g, '\\$&');
}

Mit dieser Funktion werden alle Zeichen ausgeblendet, mit Ausnahme derjenigen, deren Syntax in zukünftigen Varianten für reguläre Ausdrücke ausdrücklich nicht mehr gewährleistet ist.


Betrachten Sie diesen Edge-Fall als besonders hygienisch:

var s = '';
new RegExp('(choice1|choice2|' + regExpEscape(s) + ')');

Dies sollte in JavaScript gut kompilieren, wird aber in einigen anderen Varianten nicht. Wenn Sie beabsichtigen, zu einer anderen Variante überzugehen, sollte der Null-Fall von s === '' Unabhängig überprüft werden.

var s = '';
new RegExp('(choice1|choice2' + (s ? '|' + regExpEscape(s) : '') + ')');
37
Pi Marillion

Mozilla Developer Network - Handbuch zu regulären Ausdrücken bietet diese Escape-Funktion:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
21
quietmint

Im Autocomplete-Widget von jQueryUI (Version 1.9.1) wird ein etwas anderer regulärer Ausdruck (Zeile 6753) verwendet. Dies ist der reguläre Ausdruck in Kombination mit dem @ Bobince-Ansatz.

RegExp.escape = function( value ) {
     return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
21
Pierluc SS

Nichts sollte Sie davon abhalten, jedes nicht-alphanumerische Zeichen zu maskieren:

usersString.replace(/(?=\W)/g, '\\');

Sie verlieren ein gewisses Maß an Lesbarkeit, wenn Sie re.toString() ausführen, aber Sie gewinnen viel Einfachheit (und Sicherheit).

Laut ECMA-262 sind reguläre Ausdrücke "Syntaxzeichen" einerseits immer nicht alphanumerisch, so dass das Ergebnis sicher ist, und spezielle Escape-Sequenzen (\d, \w, \n) Sind immer alphanumerisch, so dass keine falschen Steuerzeichen entstehen.

12
daluege

Es gibt einen ES7-Vorschlag für RegExp.escape unter https://github.com/benjamingr/RexExp.escape/ und eine Polyfill unter https://github.com/ljharb) /regexp.escape .

10
user663031

Dies ist eine kürzere Version.

RegExp.escape = function(s) {
    return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}

Dies schließt die Nicht-Meta-Zeichen von %, &, ' Und , Ein, aber die JavaScript-RegExp-Spezifikation erlaubt dies.

6
kzh
escapeRegExp = function(str) {
  if (str == null) return '';
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
3
Ravi Gadhia

Anstatt nur Zeichen zu maskieren, die Probleme in Ihrem regulären Ausdruck verursachen (z. B. eine Blacklist), sollten Sie stattdessen eine Whitelist verwenden. Auf diese Weise wird jedes Zeichen als verdorben angesehen, sofern es nicht übereinstimmt.

Nehmen Sie für dieses Beispiel den folgenden Ausdruck an:

RegExp.escape('be || ! be');

Diese Whitelists Buchstaben, Zahlen und Leerzeichen:

RegExp.escape = function (string) {
    return string.replace(/([^\w\d\s])/gi, '\\$1');
}

Kehrt zurück:

"be \|\| \! be"

Dies kann Zeichen entgehen, die nicht entkommen müssen, behindert jedoch nicht Ihren Ausdruck (möglicherweise einige geringfügige Zeitstrafen - aber es lohnt sich aus Sicherheitsgründen).

3
bashaus

XRegExp hat eine Escape-Funktion:

XRegExp.escape('Escaped? <.>'); // -> 'Escaped\?\ <\.>'

Mehr unter: http://xregexp.com/api/#escape

3

Ein anderer (viel sichererer) Ansatz besteht darin, alle Zeichen (und nicht nur einige spezielle, die wir derzeit kennen) mit dem Unicode-Escape-Format \u{code}:

function escapeRegExp(text) {
    return Array.from(text)
           .map(char => `\\u{${char.charCodeAt(0).toString(16)}}`)
           .join('');
}

console.log(escapeRegExp('a.b')); // '\u{61}\u{2e}\u{62}'

Bitte beachten Sie, dass Sie das u -Flag übergeben müssen, damit diese Methode funktioniert:

var expression = new RegExp(escapeRegExp(usersString), 'u');
0
soheilpro

Die Funktionen in den anderen Antworten sind überflüssig, um ganze reguläre Ausdrücke zu maskieren (sie können nützlich sein, um reguläre Ausdrücke zu maskieren Teile, die später zu größeren regulären Ausdrücken verkettet werden).

Wenn Sie einen vollständigen regulären Ausdruck verlassen und damit fertig sind, zitieren Sie die Metazeichen, die entweder eigenständig sind (., ?, +, *, ^, $, |, \) oder etwas anfangen ((, [, {) ist alles, was du brauchst:

String.prototype.regexEscape = function regexEscape() {
  return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};

Und ja, es ist enttäuschend, dass JavaScript nicht über eine solche Funktion verfügt.

0
Dan Dascalescu