Ich habe einen regulären Ausdruck geschrieben, der in einem bestimmten Programm gut funktioniert (grep, sed, awk, perl, python, ruby, ksh, bash, zsh, find, emacs, vi, vim, gedit, …). Aber wenn ich es in einem anderen Programm (oder auf einer anderen Unix-Variante) verwende, passt es nicht mehr. Warum?
Akzeptierte Antwort:
Leider haben verschiedene Tools aus historischen Gründen eine leicht unterschiedliche Syntax für reguläre Ausdrücke, und manchmal haben einige Implementierungen Erweiterungen, die von anderen Tools nicht unterstützt werden. Es gibt zwar Gemeinsamkeiten, aber anscheinend hat jeder Tool-Autor andere Entscheidungen getroffen.
Die Folge davon ist, dass Sie einen regulären Ausdruck, der in einem Tool funktioniert, möglicherweise ändern müssen, damit er in einem anderen Tool funktioniert. Die Hauptunterschiede zwischen gängigen Tools sind:
- ob die Operatoren
+?|(){}
erfordert einen umgekehrten Schrägstrich; - welche Erweiterungen über die Grundlagen hinaus unterstützt werden
.[]*^$
und normalerweise+?|()
In dieser Antwort liste ich die wichtigsten Standards auf. Einzelheiten finden Sie in der Dokumentation der von Ihnen verwendeten Tools.
Der Wikipedia-Vergleich von Engines für reguläre Ausdrücke enthält eine Tabelle, in der die Funktionen aufgeführt sind, die von gängigen Implementierungen unterstützt werden.
Grundlegende reguläre Ausdrücke (BRE)
Grundlegende reguläre Ausdrücke werden durch den POSIX-Standard kodifiziert. Es ist die Syntax, die von grep
verwendet wird , sed
und vi
. Diese Syntax bietet die folgenden Funktionen:
^
und$
passen nur am Anfang und am Ende einer Zeile..
entspricht jedem Zeichen (oder jedem Zeichen außer einem Zeilenumbruch).[…]
stimmt mit einem der in Klammern aufgeführten Zeichen überein (Zeichensatz). Wenn das erste Zeichen nach der öffnenden Klammer ein^
ist , werden stattdessen die nicht aufgeführten Zeichen abgeglichen. Um einen]
einzufügen , setzen Sie es direkt nach dem öffnenden[
(oder nach[^
wenn es eine negative Menge ist). Wenn-
zwischen zwei Zeichen steht, bezeichnet es einen Bereich; um einen wörtlichen-
einzuschließen , platzieren Sie es dort, wo es nicht als Bereich geparst werden kann.- Backslash vor einem von
^$.*[
setzt das nächste Zeichen in Anführungszeichen. *
stimmt 0, 1 oder öfter mit dem vorhergehenden Zeichen oder Unterausdruck überein.(…)
ist eine syntaktische Gruppe zur Verwendung mit*
Operator oder Rückverweise undDIGIT
Ersatz.- Rückverweise
1
,2
, … stimmen genau mit dem Text überein, der von der entsprechenden Gruppe gefunden wurde, z.(fo*)(ba*)1
entsprichtfoobaafoo
aber nichtfoobaafo
. Es gibt keine Standardmethode, um sich auf die 10. Gruppe und darüber hinaus zu beziehen (die Standardbedeutung von10
ist die erste Gruppe gefolgt von einem).
Die folgenden Funktionen sind ebenfalls Standard, fehlen aber in einigen eingeschränkten Implementierungen:
{m,n}
stimmt mit dem vorhergehenden Zeichen oder Unterausdruck zwischen m überein zu n mal; n oder m weggelassen werden kann, und{m}
bedeutet genau m .- In Klammern können Zeichenklassen verwendet werden, zum Beispiel
[[:alpha:]]
passt zu jedem Buchstaben. Moderne Implementierungen von Klammerausdrücken) enthalten auch Sortierelemente wie[.ll.]
und Äquivalenzklassen wie[=a=]
.
Das Folgende sind gängige Erweiterungen (insbesondere in GNU-Tools), aber sie sind nicht in allen Implementierungen zu finden. Schlagen Sie im Handbuch des von Ihnen verwendeten Tools nach.
|
zur Abwechslung:foo|bar
entsprichtfoo
oderbar
.?
(kurz für{0,1}
) und+
(kurz für{1,}
) stimmen höchstens einmal bzw. mindestens einmal mit dem vorhergehenden Zeichen oder Teilausdruck überein.n
entspricht einem Zeilenumbruch,t
entspricht einem Tab usw.w
passt zu jedem Wortbestandteil (kurz für[_[:alnum:]]
aber mit Variationen bei der Lokalisierung) undW
entspricht jedem Zeichen, das kein Wortbestandteil ist.<
und>
Übereinstimmung mit der leeren Zeichenfolge nur am Anfang bzw. am Ende eines Wortes;b
passt entweder undB
stimmt mitb
überein nicht.
Beachten Sie, dass Tools ohne |
-Operator verfügen nicht über die volle Leistungsfähigkeit regulärer Ausdrücke. Rückverweise ermöglichen einige zusätzliche Dinge, die mit regulären Ausdrücken im mathematischen Sinne nicht möglich sind.
Erweiterte reguläre Ausdrücke (ERE)
Erweiterte reguläre Ausdrücke werden durch den POSIX-Standard kodifiziert. Ihr Hauptvorteil gegenüber BRE ist die Regelmäßigkeit:Alle Standardoperatoren sind reine Satzzeichen, ein umgekehrter Schrägstrich vor einem Satzzeichen steht immer in Anführungszeichen. Es ist die von awk
verwendete Syntax , grep -E
oder egrep
, GNU sed -r
, und bashs =~
Operator. Diese Syntax bietet die folgenden Funktionen:
^
und$
passen nur am Anfang und am Ende einer Zeile..
entspricht jedem Zeichen (oder jedem Zeichen außer einem Zeilenumbruch).[…]
stimmt mit einem der in Klammern aufgeführten Zeichen überein (Zeichensatz). Ergänzung mit einem vorangestellten^
und Bereiche funktionieren wie in BRE (siehe oben). Zeichenklassen können verwendet werden, fehlen aber bei einigen Implementierungen. Moderne Implementierungen unterstützen auch Äquivalenzklassen und Sortierelemente. Ein umgekehrter Schrägstrich in Klammern zitiert das nächste Zeichen in einigen, aber nicht allen Implementierungen; Verwenden Sie\
um einen umgekehrten Schrägstrich für Portabilität zu bedeuten.(…)
ist eine syntaktische Gruppe zur Verwendung mit*
oderDIGIT
Ersatz.|
zur Abwechslung:foo|bar
entsprichtfoo
oderbar
.*
,+
und?
stimmt mehrmals mit dem vorhergehenden Zeichen oder Teilausdruck überein:0 oder mehr für*
, 1 oder mehr für+
, 0 oder 1 für?
.- Backslash setzt das nächste Zeichen in Anführungszeichen, wenn es nicht alphanumerisch ist.
{m,n}
stimmt mit dem vorhergehenden Zeichen oder Unterausdruck zwischen m überein und n Zeiten (fehlen bei einigen Implementierungen); n oder m weggelassen werden kann, und{m}
bedeutet genau m .- Einige gebräuchliche Erweiterungen wie in BRE:
DIGIT
Rückverweise (insbesondere fehlen in awk, außer in der busybox-Implementierung, wo Sie$0 ~ "(...)\1"
verwenden können ); Sonderzeichenn
,t
, etc.; Wortgrenzenb
undB
, Wortbestandteileb
undB
, …
PCRE (Perl-kompatible reguläre Ausdrücke)
PCRE sind Erweiterungen von ERE, die ursprünglich von Perl eingeführt und von GNU grep -P
übernommen wurden und viele moderne Tools und Programmiersprachen , normalerweise über die PCRE-Bibliothek. Siehe die Perl-Dokumentation für nette Formatierungen mit Beispielen. Nicht alle Funktionen der neuesten Version von Perl werden von PCRE unterstützt (z. B. wird die Ausführung von Perl-Code nur in Perl unterstützt). Eine Zusammenfassung der unterstützten Funktionen finden Sie im PCRE-Handbuch. Die wichtigsten Ergänzungen zu ERE sind:
(?:…)
ist eine nicht einfangende Gruppe:wie(…)
, zählt aber nicht für Rückverweise.(?=FOO)BAR
(Lookahead) stimmt mitBAR
überein , aber nur, wenn es auch eine Übereinstimmung fürFOO
gibt an der gleichen Position beginnen. Dies ist am nützlichsten, um eine Übereinstimmung zu verankern, ohne den folgenden Text in die Übereinstimmung aufzunehmen:foo(?=bar)
entsprichtfoo
aber nur wenn daraufbar
folgt .(?!FOO)BAR
(negatives Lookahead) stimmt mitBAR
überein , aber es gibt auch keine Übereinstimmung fürFOO
an der gleichen Stelle. Zum Beispiel(?!foo)[a-z]+
entspricht jedem kleingeschriebenen Wort, das nicht mitfoo
beginnt;[a-z]+(?![0-9)
entspricht jedem kleingeschriebenen Wort, dem keine Ziffer folgt (also infoo123
, stimmt es mitfo
überein aber nichtfoo
).(?<=FOO)BAR
(Lookbehind) stimmt mitBAR
überein , aber nur, wenn ihm unmittelbar eine Übereinstimmung fürFOO
vorausgeht .FOO
muss eine bekannte Länge haben (Sie können keine Wiederholungsoperatoren wie*
verwenden ). Dies ist am nützlichsten, um eine Übereinstimmung zu verankern, ohne den vorangehenden Text in die Übereinstimmung aufzunehmen:(?<=^| )foo
entsprichtfoo
aber nur, wenn ihm ein Leerzeichen oder der Anfang der Zeichenfolge vorangestellt ist.(?<!FOO)BAR
(negatives Lookbehind) stimmt mitBAR
überein , aber nur, wenn ihm nicht unmittelbar eine Übereinstimmung fürFOO
vorausgeht .FOO
muss eine bekannte Länge haben (Sie können keine Wiederholungsoperatoren wie*
verwenden ). Dies ist am nützlichsten, um eine Übereinstimmung zu verankern, ohne den vorangehenden Text in die Übereinstimmung aufzunehmen:(?<![a-z])foo
entsprichtfoo
aber nur, wenn ihm kein Kleinbuchstabe vorangestellt ist.
Emacs
Die Syntax von Emacs liegt zwischen BRE und ERE. Neben Emacs ist dies die Standard-Syntax für -regex
in GNU find. Emacs bietet die folgenden Operatoren:
^
,$
,.
,[…]
,*
,+
,?
wie in ERE(…)
,|
,{…}
,DIGIT
wie in BRE- mehr Backslash-Buchstabenfolgen;
<
und>
für Wortgrenzen; und mehr in neueren Versionen von Emacs, die in anderen Engines mit einer Emacs-ähnlichen Syntax oft nicht unterstützt werden.
Muschelkugeln
Shell-Globs (Wildcards) führen einen Mustervergleich mit einer Syntax durch, die sich vollständig von regulären Ausdrücken unterscheidet und weniger leistungsfähig ist. Neben Shells sind diese Wildcards auch mit anderen Tools wie find -name
verfügbar und rsync-Filter. POSIX-Muster umfassen die folgenden Merkmale:
?
entspricht jedem einzelnen Zeichen.[…]
ist ein Zeichensatz wie in gängigen Syntaxen für reguläre Ausdrücke. Einige Shells unterstützen keine Zeichenklassen. Einige Shells erfordern!
statt^
um die Menge zu negieren.*
entspricht einer beliebigen Zeichenfolge (häufig außer/
beim Abgleich von Dateipfaden; wenn/
ist von*
ausgeschlossen , dann**
enthält manchmal/
, aber sehen Sie in der Dokumentation des Tools nach).- Backslash steht für das nächste Zeichen.
Ksh bietet zusätzliche Funktionen, die dem Mustervergleich die volle Leistungsfähigkeit regulärer Ausdrücke verleihen. Diese Funktionen sind auch in Bash verfügbar, nachdem shopt -s extglob
ausgeführt wurde . Zsh hat eine andere Syntax, kann aber auch die Syntax von ksh nach setopt ksh_glob
unterstützen .