it-swarm.com.de

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

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

Anders verhält es sich beispielsweise mit Python, sed, grep, awk, Perl, umbenennen, Apache, find und so weiter. 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?

359
Igor Katson

Welche Charaktere Sie brauchen und welchen Sie nicht entkommen dürfen, hängt in der Tat von der Regex-Variante ab, mit der Sie arbeiten.

Entziehen Sie sich für PCRE und die meisten anderen so genannten Perl-kompatiblen Aromen diesen externen Zeichenklassen:

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

und diese inneren Zeichenklassen:

^-]\

Entziehen Sie sich für POSIX Extended Regexes (ERE) diesen externen Zeichenklassen (wie PCRE):

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

Das Escapieren anderer Zeichen ist ein Fehler bei POSIX ERE.

In Zeichenklassen ist der Backslash ein Literal in regulären POSIX-Ausdrücken. Sie können es nicht verwenden, um irgendetwas zu entkommen. Sie müssen "clevere Platzierung" verwenden, wenn Sie Zeichenklassen-Metazeichen als Literale einschließen möchten. Setzen Sie das ^ irgendwo außer am Anfang, das] am Anfang und das - am Anfang oder am Ende der Zeichenklasse, um diese wörtlich abzugleichen, z.

[]^-]

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

.^$*[\

Entgegengesetzte Klammern und geschweifte Klammern in BREs geben ihnen die besondere Bedeutung, die ihre Versionen ohne Aussparung in EREs haben. Einige Implementierungen (z. B. GNU) geben auch anderen Zeichen eine besondere Bedeutung, wenn sie maskiert werden, wie z. B. \? und +. Das Escapieren eines anderen Zeichens als. ^ $ * () {} Ist normalerweise ein Fehler bei BREs.

Innerhalb von Zeichenklassen folgen BREs der gleichen Regel wie EREs.

Wenn dir das alles Kopfzerbrechen bereitet, nimm dir eine Kopie von RegexBuddy . Klicken Sie auf der Registerkarte Erstellen auf Token einfügen und dann auf Literal. RegexBuddy fügt bei Bedarf Fluchten hinzu.

338
Jan Goyvaerts

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

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


Legacy RegEx-Geschmacksrichtungen (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 Zeichenklasse: . ^ $ * + ? ( ) [ { } \ |
Innerhalb einer Zeichenklasse: ^ - [ ]

BRE/ed/grep/sed

Außerhalb einer Zeichenklasse: . ^ $ * [ \
Innerhalb einer Zeichenklasse: ^ - [ ]
Für Literale nicht entkommen: + ? ( ) { } |
Für normales Regex-Verhalten: \+ \? \( \) \{ \} \|


Anmerkungen

  • Wenn Sie sich über ein bestimmtes Zeichen nicht sicher sind, können Sie es wie folgt maskieren: \xFF
  • Alphanumerische Zeichen können nicht mit einem Backslash versehen werden
  • Beliebige Symbole können in PCRE mit einem Backslash maskiert werden, nicht jedoch BRE/ERE (sie müssen nur bei Bedarf maskiert werden). Für PCRE muss ] - Nur innerhalb einer Zeichenklasse maskiert werden, ich habe sie jedoch der Einfachheit halber in einer einzigen Liste gespeichert
  • Bei Zeichenfolgen mit Anführungszeichen müssen auch die umgebenden Anführungszeichen mit Escapezeichen versehen werden, und häufig werden die Backslashes verdoppelt (wie "(\")(/)(\\.)" im Vergleich zu /(")(\/)(\.)/ in JavaScript).
  • Abgesehen von Escape-Zeichen können verschiedene Regex-Implementierungen verschiedene Modifikatoren, Zeichenklassen, Anker, Quantifikatoren und andere Funktionen unterstützen. Weitere Informationen finden Sie unter regular-expressions.info oder verwenden Sie regex101.com , um Ihre Ausdrücke live zu testen
56
Beejor

Leider gibt es nicht wirklich eine Reihe von Escape-Codes, da diese je nach verwendeter Sprache variieren.

Wenn Sie jedoch eine Seite wie die Regular Expression Tools Page oder diese Regular Expression Cheatsheet beibehalten, können Sie die Dinge schnell herausfiltern.

22
Dillie-O

POSIX erkennt mehrere Variationen von regulären Ausdrücken - einfache reguläre Ausdrücke (BRE) und erweiterte reguläre Ausdrücke (ERE). Und selbst dann gibt es Macken wegen 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.

Schauen Sie sich Jeff Friedls Mastering Regular Expressions Buch an.

5

Leider werden die Bedeutungen von Dingen wie (und\(zwischen regulären Ausdrücken im Emacs-Stil und den meisten anderen Stilen ausgetauscht. Wenn Sie also versuchen, diese zu umgehen, tun Sie möglicherweise das Gegenteil von dem, was Sie wollen.

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

4
Darron

Manchmal ist ein einfaches Entkommen mit den von Ihnen aufgelisteten Zeichen nicht möglich. Wenn Sie beispielsweise einen Backslash verwenden, um eine Klammer zu umgehen, funktioniert dies in sed nicht auf der linken Seite einer Substitutionszeichenfolge

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

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

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

das finde ich funktioniert für die meisten regexp implementierungen.

Übrigens: Zeichenklassen sind hübsche reguläre Ausdrücke für Vanilla, daher funktionieren sie in den meisten Situationen, in denen Sie in regulären Ausdrücken maskierte Zeichen benötigen.

Edit: Nach dem folgenden Kommentar möchte ich nur die Tatsache erwähnen, dass Sie auch den Unterschied zwischen Automaten mit und ohne endlichen Zustand berücksichtigen müssen Automaten beim Betrachten des Verhaltens der Regexp-Auswertung.

Vielleicht möchten Sie sich "the shiny ball book", auch bekannt als Effective Perl ( bereinigter Amazon-Link ), genauer das Kapitel über reguläre Ausdrücke ansehen, um ein Gefühl für die Unterschiede bei den Bewertungsarten der regulären Ausdrücke zu bekommen.

Nicht alle Welt ist ein PCRE!

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

Ah, die Freude, in den späten 70ern an der UNSW zu studieren! (-:

4
Rob Wells

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

4
Charlie Martin

Um zu wissen, wann und was ohne Versuche zu entkommen ist, muss die Kette der Kontexte, durch die die Zeichenfolge verläuft, genau verstanden werden. Sie geben die Zeichenfolge von der weitesten Seite bis zu ihrem endgültigen Ziel an. Dies ist der Speicher, der vom Parsing-Code für reguläre Ausdrücke verwaltet 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 jedoch auch um eine interaktive Befehlszeile oder eine in einer Shell-Skriptdatei angegebene Befehlszeile handeln innerhalb einer Variablen im Speicher, die vom Code erwähnt wird, oder eines (String-) Arguments durch weitere Auswertung oder eines Strings, der Code enthält, der dynamisch mit einer beliebigen Art von Kapselung generiert wurde ...

In jedem dieser Kontexte wurden einige Zeichen mit speziellen Funktionen zugewiesen.

Wenn Sie das Zeichen buchstäblich übergeben möchten, ohne seine spezielle Funktion (kontextbezogen) zu verwenden, müssen Sie es für den nächsten Kontext entziehen ... was möglicherweise einige andere entziehende Zeichen erfordert, die möglicherweise zusätzlich erforderlich sind Escapezeichen in den vorhergehenden Kontexten. Darüber hinaus kann es Dinge wie Zeichenkodierung geben (das heimtückischste ist utf-8, da es wie ASCII für gebräuchliche Zeichen aussieht, aber es kann optional auch vom Terminal interpretiert werden, abhängig von seinen Einstellungen verhalten sich anders, dann ist das Encoding-Attribut von HTML/XML notwendig, um den Prozess genau richtig zu verstehen.

Z.B. Ein regulärer Ausdruck in der Befehlszeile, der mit Perl -npe Beginnt, muss an eine Reihe von exec Systemaufrufen übergeben werden, die als Pipe die Dateihandles verbinden. Jeder dieser Systemaufrufe von exec hat nur eine Liste von Argumenten, die durch (nicht maskierte) Leerzeichen getrennt wurden, und möglicherweise Pipes (|) und Umleitungen (> N> N> & M), Klammern, interaktive Erweiterung von * und ?, $(()) ... (all dies sind Sonderzeichen, die vom * sh verwendet werden und im nächsten Kontext möglicherweise mit dem Zeichen des regulären Ausdrucks interferieren. Sie werden jedoch in der Reihenfolge ausgewertet: vor der Befehlszeile. Der Befehl Die Zeile wird von einem Programm als bash/sh/csh/tcsh/zsh gelesen. Im Wesentlichen in doppelten oder einfachen Anführungszeichen ist die Escape-Anweisung einfacher, es ist jedoch nicht erforderlich, einen String in der Befehlszeile in Anführungszeichen zu setzen, da meistens das Leerzeichen vorangestellt werden muss Backslash und das Anführungszeichen sind nicht erforderlich, so dass die Erweiterungsfunktion für Zeichen * und? verfügbar ist. Dabei wird jedoch ein anderer Kontext als innerhalb des Anführungszeichens analysiert. Wenn die Befehlszeile ausgewertet wird, erhält der Regexp im Speicher (nicht wie in der Befehlszeile geschrieben) die gleiche Behandlung wie in einer Quelldatei. Für reguläre Ausdrücke gibt es einen Zeichensatzkontext in eckigen Klammern []. Perl-reguläre Ausdrücke können in Anführungszeichen gesetzt 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ähnte, finden Sie das regexp-Escape bei Versuchen. Dies liegt wahrscheinlich daran, dass der unterschiedliche Kontext unterschiedliche Zeichen hat, die Ihre Erinnerung an Versuche verwirrten (oft ist ein Backslash das Zeichen, das in diesen unterschiedlichen Kontexten verwendet wird, um ein literales Zeichen anstelle seiner Funktion zu entkommen ).

2
Marco Munari

Für PHP ist es immer sicher, "\" vor eine nicht-alphanumerische Zahl zu stellen, um anzugeben, dass sie für sich selbst steht. " - http://php.net/manual/en/regexp.reference.escape.php .

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

Um Regex-Mustervariablen (oder Teilvariablen) in PHP verwenden Sie preg_quote ()

2
zylstra

https://perldoc.Perl.org/perlre.html#Quoting-metacharacters und https://perldoc.Perl.org/functions/quotemeta.html

In der offiziellen Dokumentation werden solche Zeichen als Metazeichen bezeichnet. Beispiel für ein Zitat:

my $regex = quotemeta($string)
s/$regex/something/
0
MUY Belgium