Antworten:
Der wichtigste Teil sind die Konzepte. Sobald Sie verstanden haben, wie die Bausteine funktionieren, betragen die Unterschiede in der Syntax kaum mehr als milde Dialekte. Eine Ebene über der Syntax Ihrer Engine für reguläre Ausdrücke ist die Syntax der von Ihnen verwendeten Programmiersprache. Sprachen wie Perl beseitigen den größten Teil dieser Komplikation, aber Sie müssen andere Überlegungen berücksichtigen, wenn Sie reguläre Ausdrücke in einem C-Programm verwenden.
Wenn Sie reguläre Ausdrücke als Bausteine betrachten, die Sie nach Belieben mischen und anpassen können, lernen Sie, wie Sie Ihre eigenen Muster schreiben und debuggen, aber auch wie Sie von anderen geschriebene Muster verstehen.
Konzeptionell sind die einfachsten regulären Ausdrücke wörtliche Zeichen. Das Muster N
entspricht dem Zeichen 'N'.
Reguläre Ausdrücke nebeneinander stimmen mit Sequenzen überein. Zum Beispiel das MusterNick
stimmt mit der Sequenz 'N' überein, gefolgt von 'i', gefolgt von 'c', gefolgt von 'k'.
Wenn Sie jemals unter grep
Unix verwendet haben - auch wenn Sie nur nach normal aussehenden Zeichenfolgen suchen -, haben Sie bereits reguläre Ausdrücke verwendet! (Das re
in grep
bezieht sich auf reguläre Ausdrücke.)
Wenn Sie nur ein wenig Komplexität hinzufügen, können Sie entweder 'Nick' oder 'Nick' mit dem Muster abgleichen [Nn]ick
. Der Teil in eckigen Klammern ist eine Zeichenklasse , dh er entspricht genau einem der eingeschlossenen Zeichen. Sie können auch Bereiche in Zeichenklassen verwenden, sodass [a-c]
entweder 'a' oder 'b' oder 'c' übereinstimmen.
Das Muster .
ist etwas Besonderes: Anstatt nur einem wörtlichen Punkt zu entsprechen, stimmt es mit jedem Zeichen † überein . Es ist konzeptionell dasselbe wie die wirklich große Charakterklasse [-.?+%$A-Za-z0-9...]
.
Stellen Sie sich Charakterklassen als Menüs vor: Wählen Sie nur eines aus.
Durch .
die Verwendung können Sie viel Tipparbeit sparen, und es gibt andere Verknüpfungen für häufig verwendete Muster. Angenommen, Sie möchten einer Ziffer entsprechen: Eine Möglichkeit, dies zu schreiben, ist [0-9]
. Ziffern sind ein häufiges Übereinstimmungsziel, daher können Sie stattdessen die Verknüpfung verwenden \d
. Andere sind \s
(Leerzeichen) und \w
(Wortzeichen: alphanumerisch oder Unterstrich).
Die Großbuchstabenvarianten sind ihre Ergänzungen und passen daher beispielsweise zu \S
allen Nicht- Leerzeichen.
Von dort aus können Sie Teile Ihres Musters mit Quantifizierern wiederholen . Beispielsweise ab?c
stimmt das Muster mit 'abc' oder 'ac' ?
überein , da der Quantifizierer das zu ändernde Untermuster optional macht. Andere Quantifizierer sind
*
(null oder mehrmals)+
(einmal oder mehrmals){n}
(genau n mal){n,}
(mindestens n mal){n,m}
(mindestens n- mal, aber nicht mehr als m- mal)Wenn Sie einige dieser Blöcke zusammenfügen, [Nn]*ick
stimmt das Muster mit allen überein
Das erste Spiel zeigt eine wichtige Lektion: *
Immer erfolgreich! Jedes Muster kann nullmal übereinstimmen.
Einige andere nützliche Beispiele:
[0-9]+
(und sein Äquivalent \d+
) stimmt mit einer nicht negativen Ganzzahl überein\d{4}-\d{2}-\d{2}
Übereinstimmungsdaten formatiert wie 2019-01-01Ein Quantifizierer ändert das Muster unmittelbar links davon. Sie können erwarten 0abc+0
, dass '0abc0', '0abcabc0' usw. übereinstimmen, aber das Muster unmittelbar links vom Plus-Quantifizierer ist c
. Dies bedeutet, dass 0abc+0
Übereinstimmungen mit '0abc0', '0abcc0', '0abccc0' usw. übereinstimmen.
Verwenden Sie, um eine oder mehrere Sequenzen von 'abc' mit Nullen an den Enden abzugleichen 0(abc)+0
. Die Klammern bezeichnen ein Untermuster, das als Einheit quantifiziert werden kann. Es ist auch üblich, dass Engines für reguläre Ausdrücke den Teil des Eingabetextes speichern oder "erfassen", der einer Gruppe in Klammern entspricht. Das Extrahieren von Bits auf diese Weise ist viel flexibler und weniger fehleranfällig als das Zählen von Indizes und substr
.
Früher haben wir einen Weg gesehen, entweder 'Nick' oder 'Nick' zu finden. Ein anderer ist im Wechsel wie in Nick|nick
. Denken Sie daran, dass der Wechsel alles zu seiner Linken und alles zu seiner Rechten umfasst. Verwenden Sie Klammern , die Gruppierung den Umfang zu begrenzen |
, zum Beispiel , (Nick|nick)
.
In einem anderen Beispiel könnten Sie äquivalent schreiben [a-c]
als a|b|c
, aber dies ist wahrscheinlich nicht optimal, da viele Implementierungen davon ausgehen, dass Alternativen Längen größer als 1 haben.
Obwohl einige Zeichen mit sich selbst übereinstimmen, haben andere eine besondere Bedeutung. Das Muster \d+
stimmt nicht mit dem Backslash überein, gefolgt von Kleinbuchstaben D, gefolgt von einem Pluszeichen: Um dies zu erhalten, würden wir verwenden \\d\+
. Ein Backslash entfernt die besondere Bedeutung des folgenden Zeichens.
Quantifizierer für reguläre Ausdrücke sind gierig. Dies bedeutet, dass sie so viel Text wie möglich abgleichen, während das gesamte Muster erfolgreich übereinstimmt.
Angenommen, die Eingabe lautet
"Hallo", sagte sie, "wie geht es dir?"
Sie können davon ausgehen ".+"
, dass nur "Hallo" übereinstimmt, und werden dann überrascht sein, wenn Sie sehen, dass es von "Hallo" bis "Sie?" Übereinstimmt.
Fügen Sie ?
dem Quantifizierer ein Extra hinzu , um von gierig zu dem zu wechseln, was Sie für vorsichtig halten . Jetzt verstehen Sie, wie \((.+?)\)
das Beispiel aus Ihrer Frage funktioniert. Es entspricht der Reihenfolge einer wörtlichen linken Klammer, gefolgt von einem oder mehreren Zeichen, und wird durch eine rechte Klammer abgeschlossen.
Wenn Ihre Eingabe '(123) (456)' ist, ist die erste Aufnahme '123'. Nicht gierige Quantifizierer möchten, dass der Rest des Musters so schnell wie möglich mit dem Abgleich beginnt.
(In Bezug auf Ihre Verwirrung kenne ich keinen Dialekt mit regulären Ausdrücken, in dem ((.+?))
das Gleiche der Fall wäre. Ich vermute, dass irgendwo auf dem Weg etwas bei der Übertragung verloren gegangen ist.)
Verwenden Sie das spezielle Muster ^
, um nur am Anfang Ihrer Eingabe und $
nur am Ende übereinzustimmen. Es ist eine nützliche Technik, mit Ihren Mustern "Buchstützen" zu machen, in denen Sie sagen: "Ich weiß, was vorne und hinten ist, aber geben Sie mir alles dazwischen".
Angenommen, Sie möchten Kommentare des Formulars abgleichen
-- This is a comment --
du würdest schreiben ^--\s+(.+)\s+--$
.
Reguläre Ausdrücke sind rekursiv. Nachdem Sie diese Grundregeln verstanden haben, können Sie sie beliebig kombinieren.
†: Die obige Aussage, die .
mit jedem Charakter übereinstimmt, ist eine Vereinfachung für pädagogische Zwecke, die nicht unbedingt wahr ist. Punkt entspricht jedem Zeichen außer Zeilenumbruch, "\n"
aber in der Praxis erwarten Sie selten ein Muster .+
, das eine Zeilenumbruchgrenze überschreitet. Perl-Regexes haben einen /s
Schalter und Java Pattern.DOTALL
, um beispielsweise .
jedem Zeichen eine Übereinstimmung zu geben. Für Sprachen, die keine solche Funktion haben, können Sie so etwas wie [\s\S]
"jedes Leerzeichen oder jedes Nicht-Leerzeichen" verwenden, mit anderen Worten alles.
a{,m}
handelt, zumindest in Javascript, Perl und Python keine Sache ist.