Wie funktioniert es?
Werfen Sie einen Blick auf die Automatentheorie
Kurz gesagt, jeder reguläre Ausdruck hat einen äquivalenten endlichen Automaten und kann zu einem endlichen Automaten kompiliert und optimiert werden. Die beteiligten Algorithmen finden Sie in vielen Compiler-Büchern. Diese Algorithmen werden von Unix-Programmen wie awk und grep verwendet.
Die meisten modernen Programmiersprachen (Perl, Python, Ruby, Java (und JVM-basierte Sprachen), C #) verwenden diesen Ansatz jedoch nicht. Sie verwenden einen rekursiven Backtracking-Ansatz, bei dem ein regulärer Ausdruck in einen Baum oder eine Folge von Konstrukten kompiliert wird, die verschiedene Unterabschnitte des regulären Ausdrucks darstellen. Die meisten modernen Syntaxen für "reguläre Ausdrücke" bieten Rückverweise, die außerhalb der Gruppe regulärer Sprachen liegen (sie haben keine Darstellung in endlichen Automaten) und die in einem rekursiven Rückverfolgungsansatz trivial implementiert werden können.
Die Optimierung ergibt normalerweise eine effizientere Zustandsmaschine. Beispiel: Wenn Sie aaaab | aaaac | aaaad betrachten, kann ein normaler Programmierer die einfache, aber weniger effiziente Suchimplementierung (drei Zeichenfolgen separat vergleichen) in zehn Minuten durchführen. Wenn man jedoch erkennt, dass es gleichbedeutend mit aaaa [bcd] ist, kann eine bessere Suche durchgeführt werden, indem zuerst vier 'a' gesucht werden und dann das fünfte Zeichen gegen [b, c, d] getestet wird. Der Optimierungsprozess gehörte vor vielen Jahren zu meinen Aufgaben als Compiler. Daher gehe ich davon aus, dass er auch in den meisten modernen regulären Ausdrucksmodulen verwendet wird.
Auf der anderen Seite haben Zustandsautomaten einen gewissen Vorteil, wenn sie Zeichenfolgen akzeptieren, da sie im Vergleich zu einer "trivialen Implementierung" mehr Platz beanspruchen. Stellen Sie sich ein Programm vor, mit dem die Anführungszeichen für SQL-Zeichenfolgen aufgehoben werden: 1) Beginnt und endet mit einfachen Anführungszeichen. 2) Einfache Anführungszeichen werden durch zwei aufeinanderfolgende einfache Anführungszeichen maskiert. Also: Eingabe ['a' ''] sollte Ausgabe [a '] ergeben. Bei einer Zustandsmaschine werden die aufeinanderfolgenden einfachen Anführungszeichen von zwei Zuständen behandelt. Diese beiden Zustände dienen dazu, den Eingabeverlauf so zu speichern, dass jedes Eingabezeichen genau nur einmal verarbeitet wird, wie im Folgenden dargestellt:
...
S1->'->S2
S1->*->S1, output *, * can be any other character
S2->'->S1, output '
S2->*->END, end the current string
Meiner Meinung nach kann der reguläre Ausdruck in einigen trivialen Fällen langsamer sein, aber in der Regel schneller als ein manuell erstellter Suchalgorithmus, da die Optimierung vom Menschen nicht zuverlässig durchgeführt werden kann.
(Selbst in trivialen Fällen wie dem Durchsuchen eines Strings kann eine intelligente Engine den einzelnen Pfad in der Statusübersicht erkennen und diesen Teil auf einen einfachen Stringvergleich reduzieren und das Verwalten von Status vermeiden.)
Eine bestimmte Engine aus einem Framework / einer Bibliothek kann langsam sein, da die Engine eine Reihe anderer Dinge erledigt, die ein Programmierer normalerweise nicht benötigt. Beispiel: Die Regex-Klasse in .NET erstellt eine Reihe von Objekten, einschließlich Match, Groups und Captures.