2009-12-11 14 views
7

Ich habe mehrere Regexes (eigentlich mehrere tausend), und ich muss überprüfen, ob eine Zeichenfolge mit einem dieser Regexe übereinstimmt. Es ist nicht sehr effizient, also möchte ich alle diese Regexes als eine einzige Regex zusammenführen.Verschmelzen Sie mehrere Regexe zu einem einzigen

Zum Beispiel, wenn ein diese Regexes haben:

  • 'foo * bar'
  • 'foo * zip'
  • ZAP * bar '

Ich möchte Erhalte etwas wie 'foo * (bar | zip) | zap * bar'.

Gibt es einen Algorithmus, eine Bibliothek oder ein Werkzeug, um dies zu tun?

Antwort

7

Sie können einfach die Regexes verketten mit oder (|) (und Anker für den Anfang/Ende der Zeichenfolge).

Die meisten guten Regex-Bibliotheken optimieren ihre Automaten mit endlichem Zustand, nachdem sie sie aus Ihrer Regex erstellt haben. PCRE macht das zum Beispiel.

Dieser Schritt kümmert sich normalerweise um Ihr Optimierungsproblem, dh. Sie wenden die meisten Transformationen an, die Sie "von Hand" machen müssten.

+0

Guter erster Schritt, aber Sie müssen nicht von Hand optimieren: http://www.rexegg.com/regex-optimizations.html –

0

Ich kann mir nicht vorstellen, auch wenn es möglich wäre, dass die resultierende Regex effizienter wäre.

+2

stimme ich nicht zu; Eine Regex-Suche nach "foo (?: bar | baz)" wird schneller sein als eine Suche nach "foo bar" und eine Suche nach "foo baz", da bei getrennter Suche eine Übereinstimmung (oder auch nicht) mit dem "foo" Teil zweimal. –

+1

-1 Die Art und Weise, in der der Automat gebaut wird, wird viele Fälle automatisch optimieren. Darüber hinaus können Sie die resultierende Zustandsmaschine weiter optimieren (siehe Antwort von Vlad). –

+0

ich ~ = korrigiert. Vielen Dank! – hometoast

0

Ich bezweifle es sehr, mit der Begründung, dass ein solches Werkzeug sehr komplex sein müsste, um mit all den verschiedenen Möglichkeiten, wie eine Regex kombiniert werden könnte, umzugehen.

Wenn die Regexes, die Sie haben, relativ einfach sind, wie in Ihren Beispielen, haben Sie vielleicht etwas Glück, wenn Sie Ihre eigenen schreiben.

2

In der Theorie ist eine Regex ein (nichtdeterministischer) endlicher Automat; somit können sie zusammengeführt und minimiert werden. Sie können einen Blick auf this als Ausgangspunkt nehmen.

Beachten Sie jedoch, dass dies möglicherweise nicht die richtige Antwort ist. Warum müssen Sie mit mehreren tausend regulären Ausdrücken umgehen? Ich kann die Wartehase der Hölle nur so ergründen. Vielleicht solltest du darüber nachdenken, einen Parser und eine Grammatik zu schreiben - das ist sehr einfach (und Grammatiken sind sowieso mächtiger als reguläre Ausdrücke).

+0

Einige Regex-Engines enthalten Funktionen, die in einem DFA nicht implementiert werden können, z. B. beliebige verschachtelte Klammern. Bevor Sie diesen Ansatz wählen, sollten Sie sicherstellen, dass Ihre Ausgangsregexte tatsächlich in DFAs konvertiert werden können, sodass Sie sie mit einem NFA verbinden können, den Sie dann wieder in ein DFA konvertieren und minimieren. – Techrocket9

Verwandte Themen