Welche Sonderzeichen müssen in regulären Ausdrücken maskiert werden?

389

Ich bin es leid, immer zu raten, ob ich Sonderzeichen wie ' ()[]{}|' usw. entkommen sollte, wenn ich viele Implementierungen von regulären Ausdrücken verwende.

Dies ist beispielsweise bei Python, sed, grep, awk, Perl, Umbenennen, Apache, find usw. anders. Gibt es einen Regelsatz, der festlegt, wann ich Sonderzeichen entkommen soll und wann nicht? Kommt es auf den Regexp-Typ an, wie PCRE, POSIX oder erweiterte Regexps?

Igor Katson
quelle
4
Gute Regex-Bibliotheken haben Funktionen wie " escape()", um die Verwendung beliebiger Zeichenfolgen als Regex-Teile zu ermöglichen.
ivan_pozdeev
2
Sie können Online-Regex-Ausdrucksprüfer wie gskinner.com/RegExr verwenden (kostenlos). (
Geben
2
Escape alle nicht alphanumerischen Zeichen. Zeitraum.
Salman von Abbas
2
Diese Frage wurde zu den häufig gestellten Fragen zum Stapelüberlauf für reguläre Ausdrücke unter "Andere" hinzugefügt .
Aliteralmind
1
Diese Frage wurde zu den häufig gestellten Fragen zum Stapelüberlauf für reguläre Ausdrücke unter "Escape-Sequenzen" hinzugefügt .
Aliteralmind

Antworten:

365

Welche Charaktere du musst und welchen du nicht entkommen darfst, hängt von der Regex-Variante ab, mit der du arbeitest.

Vermeiden Sie für PCRE und die meisten anderen sogenannten Perl-kompatiblen Geschmacksrichtungen die folgenden externen Zeichenklassen:

.^$*+?()[{\|

und diese innerhalb der Charakterklassen:

^-]\

Bei POSIX Extended Regexes (ERE) können Sie diese externen Zeichenklassen (wie bei PCRE) umgehen:

.^$*+?()[{\|

Das Escapezeichen anderer Zeichen ist bei POSIX ERE ein Fehler.

Innerhalb von Zeichenklassen ist der Backslash ein Literalzeichen in regulären POSIX-Ausdrücken. Sie können es nicht verwenden, um etwas zu entkommen. Sie müssen "clevere Platzierung" verwenden, wenn Sie Zeichencharakter-Metazeichen als Literale einfügen möchten. Setzen Sie das ^ irgendwo außer am Anfang, das] am Anfang und das - am Anfang oder am Ende der Zeichenklasse, um diesen wörtlich zu entsprechen, z.

[]^-]

In POSIX Basic Regular Expressions (BRE) sind dies Metazeichen, denen Sie entkommen müssen, um ihre Bedeutung zu unterdrücken:

.^$*[\

Das Entkommen von Klammern und geschweiften Klammern in BREs gibt ihnen die besondere Bedeutung, die ihre nicht entkoppelten Versionen in EREs haben. Einige Implementierungen (z. B. GNU) geben auch anderen Zeichen eine besondere Bedeutung, wenn sie maskiert werden, z. B. \? und +. Das Escapezeichen eines anderen Zeichens als. ^ $ * () {} Ist normalerweise ein Fehler bei BREs.

Innerhalb von Zeichenklassen folgen BREs der gleichen Regel wie EREs.

Wenn Ihnen das alles den Kopf verdreht , holen Sie sich eine Kopie von RegexBuddy . Klicken Sie auf der Registerkarte Erstellen auf Token einfügen und dann auf Literal. RegexBuddy fügt nach Bedarf Escapezeichen hinzu.

Jan Goyvaerts
quelle
1
Mir scheint, Sie haben das "/" vergessen, das auch außerhalb einer Klasse entkommen muss.
Jackthehipster
11
/ist kein Metazeichen in einem der von mir erwähnten Geschmacksrichtungen für reguläre Ausdrücke, daher muss die Syntax für reguläre Ausdrücke nicht maskiert werden. Wenn ein regulärer Ausdruck als Literal in einer Programmiersprache zitiert wird, dann können die Zeichenfolge oder regex Formatierungsregeln dieser Sprache benötigen /oder "oder 'maskiert werden, und erfordern sogar `\` doppelt maskiert werden.
Jan Goyvaerts
2
was ist mit Doppelpunkt, ":"? Soll es sowohl innerhalb als auch außerhalb der Charakterklassen entkommen? en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions sagt "PCRE hat konsistente Escape-Regeln:
Jedes
4
MAI entkommen kann ist nicht das gleiche wie sollte entkommen werden. Für die PCRE-Syntax muss niemals ein Literal-Doppelpunkt maskiert werden. Wenn Sie also Literal-Doppelpunkte maskieren, ist Ihre Regex nur schwerer lesbar.
Jan Goyvaerts
1
Bei Nicht-POSIX-ERE (das ich am häufigsten verwende, weil es das ist, was von Tcl implementiert wird) erzeugen das Entkommen anderer Dinge keine Fehler.
Slebetman
61

Moderne RegEx-Aromen (PCRE)

Enthält C, C ++, Delphi, EditPad, Java, JavaScript, Perl, PHP (preg), PostgreSQL, PowerGREP, PowerShell, Python, REALbasic, Real Studio, Ruby, TCL, VB.Net, VBScript, wxWidgets, XML-Schema, Xojo, XRegExp.
Die PCRE-Kompatibilität kann variieren

    Irgendwo: . ^ $ * + - ? ( ) [ ] { } \ |


Legacy RegEx Flavours (BRE / ERE)

Enthält awk, ed, egrep, emacs, GNUlib, grep, PHP (ereg), MySQL, Oracle, R, sed.
Die PCRE-Unterstützung kann in späteren Versionen oder mithilfe von Erweiterungen aktiviert werden

ERE / awk / egrep / emacs

    Außerhalb einer Charakterklasse: . ^ $ * + ? ( ) [ { } \ |
    Innerhalb einer Charakterklasse:^ - [ ]

BRE / ed / grep / sed

    Außerhalb einer Zeichenklasse: . ^ $ * [ \
    Innerhalb einer Zeichenklasse: ^ - [ ]
    Bei Literalen nicht entkommen: + ? ( ) { } |
    Bei Standard-Regex-Verhalten:\+ \? \( \) \{ \} \|


Anmerkungen

  • Wenn Sie sich über ein bestimmtes Zeichen nicht sicher sind, kann es wie folgt maskiert werden \xFF
  • Alphanumerische Zeichen können nicht mit einem Backslash maskiert werden
  • Beliebige Symbole können in PCRE mit einem Backslash maskiert werden, nicht jedoch in BRE / ERE (sie dürfen nur bei Bedarf maskiert werden). Für PCRE muss es ] -nur innerhalb einer Zeichenklasse maskiert werden, aber ich habe sie der Einfachheit halber in einer einzigen Liste gespeichert
  • Bei Zeichenfolgen in Anführungszeichen müssen auch die umgebenden Anführungszeichen maskiert und häufig mit doppelten Backslashes versehen sein (wie im "(\")(/)(\\.)"Vergleich /(")(\/)(\.)/zu JavaScript).
  • Abgesehen von Escapezeichen können verschiedene Regex-Implementierungen verschiedene Modifikatoren, Zeichenklassen, Anker, Quantifizierer und andere Funktionen unterstützen. Weitere Informationen finden Sie unter reguläre-Ausdrücke.info oder verwenden Sie regex101.com , um Ihre Ausdrücke live zu testen
Beejor
quelle
1
Ihre Antwort enthält viele Fehler, einschließlich, aber nicht beschränkt auf: Keiner Ihrer "modernen" Geschmacksrichtungen erfordert -oder ]muss außerhalb von Charakterklassen entkommen. POSIX (BRE / ERE) hat in Zeichenklassen kein Escapezeichen. Das Regex-Aroma in Delphis RTL basiert tatsächlich auf PCRE. Python, Ruby und XML haben ihre eigenen Varianten, die PCRE näher stehen als den POSIX-Varianten.
Jan Goyvaerts
1
@ JanGoyvaerts Danke für die Korrektur. Die Aromen, die Sie erwähnt haben, sind in der Tat näher an PCRE. Die Fluchten habe ich der Einfachheit halber so gehalten; Es ist einfacher, sich daran zu erinnern, überall zu fliehen, als ein paar Ausnahmen. Hauptbenutzer wissen, was los ist, wenn sie ein paar Backslashes vermeiden möchten. Wie auch immer, ich habe meine Antwort mit ein paar Klarstellungen aktualisiert, die hoffentlich einige dieser Dinge ansprechen.
Beejor
22

Leider gibt es wirklich keine Escape-Codes, da diese je nach verwendeter Sprache variieren.

Das Beibehalten einer Seite wie der Seite "Tools für reguläre Ausdrücke" oder dieses Cheatsheet für reguläre Ausdrücke kann jedoch einen großen Beitrag zum schnellen Herausfiltern leisten .

Dillie-O
quelle
1
Der Addedbytes-Spickzettel ist stark vereinfacht und weist einige offensichtliche Fehler auf. Zum Beispiel heißt es \<und \>sind Wortgrenzen, was nur in der Boost-Regex-Bibliothek (AFAIK) zutrifft. Aber anderswo heißt es <und >sind Metazeichen und müssen (zu \<und \>) entkommen , um sie buchstäblich zu finden, was in keinem Geschmack wahr ist
Alan Moore
5

Leider wird die Bedeutung von Dingen wie (und \ (zwischen regulären Ausdrücken im Emacs-Stil und den meisten anderen Stilen vertauscht. Wenn Sie also versuchen, diesen zu entkommen, tun Sie möglicherweise das Gegenteil von dem, was Sie wollen.

Sie müssen also wirklich wissen, welchen Stil Sie zitieren möchten.

Darron
quelle
5

POSIX erkennt mehrere Variationen von regulären Ausdrücken - grundlegende reguläre Ausdrücke (BRE) und erweiterte reguläre Ausdrücke (ERE). Und selbst dann gibt es Macken aufgrund der historischen Implementierungen der von POSIX standardisierten Dienstprogramme.

Es gibt keine einfache Regel, wann welche Notation verwendet werden soll oder welche Notation ein bestimmter Befehl verwendet.

Lesen Sie Jeff Friedls Mastering Regular Expressions- Buch.

Jonathan Leffler
quelle
4

Wirklich nicht. Es gibt ungefähr eine halbe Million verschiedener Regex-Syntaxen. Sie scheinen auf Perl, EMACS / GNU und AT & T im Allgemeinen zurückzuführen zu sein, aber ich werde auch immer überrascht.

Charlie Martin
quelle
4

Manchmal ist ein einfaches Entkommen mit den von Ihnen aufgelisteten Zeichen nicht möglich. Zum Beispiel funktioniert die Verwendung eines Backslashs, um einer Klammer zu entkommen, nicht auf der linken Seite einer Substitutionszeichenfolge in sed, nämlich

sed -e 's/foo\(bar/something_else/'

Ich neige dazu, stattdessen nur eine einfache Zeichenklassendefinition zu verwenden, sodass der obige Ausdruck wird

sed -e 's/foo[(]bar/something_else/'

was ich finde, funktioniert für die meisten Regexp-Implementierungen.

Übrigens sind Zeichenklassen hübsche Vanille-Regexp-Komponenten, daher funktionieren sie in den meisten Situationen, in denen Sie in Regexps maskierte Zeichen benötigen.

Bearbeiten: Nach dem Kommentar unten dachte ich nur, ich würde die Tatsache erwähnen, dass Sie auch den Unterschied zwischen Automaten mit endlichem Zustand und Automaten mit nicht endlichem Zustand berücksichtigen müssen, wenn Sie das Verhalten der Regexp-Bewertung betrachten.

Vielleicht möchten Sie sich "das glänzende Ballbuch", auch bekannt als "Effective Perl" ( bereinigter Amazon-Link ), ansehen , insbesondere das Kapitel über reguläre Ausdrücke, um ein Gefühl für den Unterschied zwischen den Bewertungsarten der Regexp-Engine zu bekommen.

Nicht die ganze Welt ist ein PCRE!

Wie auch immer, reguläre Ausdrücke sind im Vergleich zu SNOBOL so klobig ! Nun , dass war ein interessanter Programmierkurs! Zusammen mit dem auf Simula .

Ah, die Freude, Ende der 70er Jahre an der UNSW zu studieren! (-:

Rob Wells
quelle
'sed' ist ein Befehl, für den plain '(' ist nichts Besonderes, aber '\ (' ist etwas Besonderes; im Gegensatz dazu kehrt PCRE den Sinn um, also '(' ist etwas Besonderes, aber '\ (' ist es nicht. Genau das ist es) Das OP fragt nach.
Jonathan Leffler
sed ist ein * nix-Dienstprogramm, das einen der primitivsten Sätze der Regexp-Bewertung verwendet. PCRE geht nicht auf die von mir beschriebene Situation ein, da es sich um eine andere Klasse von (un) endlichen Automaten handelt, wie es reguläre Ausdrücke bewertet. Ich denke, mein Vorschlag für den Mindestsatz an Regexp-Syntax gilt immer noch.
Rob Wells
1
Auf einem POSIX-kompatiblen System verwendet sed POSIX BRE, das ich in meiner Antwort behandle. Die GNU-Version auf einem modernen Linux-System verwendet POSIX BRE mit einigen Erweiterungen.
Jan Goyvaerts
2

Für PHP "ist es immer sicher, einem nicht alphanumerischen Zeichen" \ "voranzustellen, um anzugeben, dass es für sich selbst steht." - http://php.net/manual/en/regexp.reference.escape.php .

Außer wenn es ein "oder" ist .: /

Verwenden Sie preg_quote (), um Regex-Mustervariablen (oder Teilvariablen) in PHP zu umgehen.

zylstra
quelle
2

Um zu wissen, wann und was ohne Versuche zu entkommen ist, muss man genau die Kontextkette verstehen, die der String durchläuft. Sie geben die Zeichenfolge von der entferntesten Seite bis zu ihrem endgültigen Ziel an. Dies ist der Speicher, der vom Regexp-Parsing-Code verarbeitet wird.

Beachten Sie, wie die Zeichenfolge im Speicher verarbeitet wird: Wenn es sich um eine einfache Zeichenfolge im Code oder eine in die Befehlszeile eingegebene Zeichenfolge handeln kann, kann es sich entweder um eine interaktive Befehlszeile oder eine Befehlszeile handeln, die in einer Shell-Skriptdatei angegeben ist, oder innerhalb einer Variablen im Speicher, die vom Code erwähnt wird, oder eines (Zeichenfolgen-) Arguments durch weitere Auswertung oder einer Zeichenfolge, die Code enthält, der dynamisch mit jeder Art von Kapselung generiert wird ...

Jedem dieser Kontexte wurden einige Zeichen mit besonderen Funktionen zugewiesen.

Wenn Sie das Zeichen buchstäblich übergeben möchten, ohne seine spezielle Funktion (lokal für den Kontext) zu verwenden, müssen Sie es für den nächsten Kontext maskieren ... was möglicherweise einige andere Escape-Zeichen erfordert, die möglicherweise zusätzlich benötigt werden in den vorhergehenden Kontexten entkommen. Darüber hinaus kann es Dinge wie die Zeichenkodierung geben (die heimtückischste ist utf-8, da sie für gängige Zeichen wie ASCII aussieht, aber abhängig von ihren Einstellungen optional auch vom Terminal interpretiert werden kann, sodass sie sich möglicherweise anders verhält als das Kodierungsattribut von HTML / XML, es ist notwendig, den Prozess genau richtig zu verstehen.

Beispiel: Ein regulärer Ausdruck in der Befehlszeile, der mit beginnt perl -npe, muss an eine Reihe von Exec -Systemaufrufen übertragen werden, die als Pipe die Datei handhaben. Jeder dieser Exec-Systemaufrufe enthält nur eine Liste von Argumenten, die durch (nicht maskierte) Leerzeichen getrennt wurden. und möglicherweise Pipes (|) und Umleitung (> N> N> & M), Klammern, interaktive Erweiterung von *und ?,$(())... (all dies sind Sonderzeichen, die vom * sh verwendet werden und die das Zeichen des regulären Ausdrucks im nächsten Kontext möglicherweise stören, aber in der folgenden Reihenfolge ausgewertet werden: vor der Befehlszeile. Die Befehlszeile wird von a gelesen Programmieren Sie als bash / sh / csh / tcsh / zsh, im Wesentlichen innerhalb von doppelten oder einfachen Anführungszeichen ist das Escape einfacher, aber es ist nicht erforderlich, eine Zeichenfolge in der Befehlszeile in Anführungszeichen zu setzen, da dem Leerzeichen meistens ein Backslash vorangestellt werden muss und das Anführungszeichen stehen Es ist nicht erforderlich, die Erweiterungsfunktion für die Zeichen * und? verfügbar zu lassen, aber diese Analyse unterscheidet sich von einem anderen Kontext als im Anführungszeichen. Wenn die Befehlszeile ausgewertet wird, wird der im Speicher erhaltene reguläre Ausdruck (nicht wie in der Befehlszeile angegeben) genauso behandelt wie er wäre in einer Quelldatei. Für reguläre Ausdrücke gibt es einen Zeichensatzkontext in eckigen Klammern [],Perl regulärer Ausdruck kann durch eine große Menge nicht alfa-numerischer Zeichen zitiert werden (z. B. m // oder m: / better / for / path: ...).

Sie haben weitere Details zu Zeichen in anderen Antworten, die sehr spezifisch für den endgültigen regulären Ausdruckskontext sind. Wie ich bereits erwähnt habe, erwähnen Sie, dass Sie das Regexp-Escape bei Versuchen finden. Dies liegt wahrscheinlich daran, dass in verschiedenen Kontexten unterschiedliche Zeichensätze vorhanden sind, die Ihre Erinnerung an Versuche verwirren (häufig ist Backslash das Zeichen, das in diesen unterschiedlichen Kontexten verwendet wird, um einem Literalzeichen anstelle seiner Funktion zu entkommen ).

Marco Munari
quelle
0

Für Ionic (Typescript) müssen Sie einen doppelten Schrägstrich verwenden, um die Zeichen zu formen. Zum Beispiel (dies entspricht einigen Sonderzeichen):

"^(?=.*[\\]\\[!¡\'=ªº\\-\\_ç@#$%^&*(),;\\.?\":{}|<>\+\\/])"

Achten Sie auf diese ] [ - _ . /Zeichen. Sie müssen doppelt aufgeschlitzt werden. Wenn Sie dies nicht tun, wird ein Tippfehler in Ihrem Code auftreten.

Alejandro del Río
quelle