Syntax für reguläre Ausdrücke für "nichts zusammenpassen"?

83

Ich habe eine Python-Template-Engine, die Regexp stark verwendet. Es verwendet Verkettung wie:

re.compile( regexp1 + "|" + regexp2 + "*|" + regexp3 + "+" )

Ich kann die einzelnen Teilzeichenfolgen (regexp1, regexp2 usw.) ändern.

Gibt es einen kleinen und leichten Ausdruck, der mit nichts übereinstimmt und den ich in einer Vorlage verwenden kann, in der ich keine Übereinstimmungen möchte? Leider wird manchmal '+' oder '*' an das Regexp-Atom angehängt, sodass ich keine leere Zeichenfolge verwenden kann - dies führt zu dem Fehler "Nichts zu wiederholen".

grigoryvp
quelle
3
Könnte der Titel besser als "Regulärer Ausdruck, der mit nichts übereinstimmt" formuliert werden? Wenn nichts übereinstimmt, bedeutet dies, dass eine leere Zeichenfolge erfolgreich übereinstimmt.
BamaPookie

Antworten:

126

Dies sollte zu nichts passen:

re.compile('$^')

Wenn Sie also regexp1, regexp2 und regexp3 durch '$ ^' ersetzen, ist es unmöglich, eine Übereinstimmung zu finden. Es sei denn, Sie verwenden den Mehrleitungsmodus.


Nach einigen Tests fand ich eine bessere Lösung

re.compile('a^')

Es ist unmöglich, eine Übereinstimmung zu erzielen, und es wird früher als bei der vorherigen Lösung fehlschlagen. Sie können a durch ein anderes Zeichen ersetzen und es wird immer unmöglich sein, es zu finden

Nadia Alramli
quelle
Das passt sicher nicht zu irgendetwas und ist leicht für die Regexp-Engine zu verarbeiten? (Ich möchte nicht, dass meine Stub-Regexps viel CPU essen)
grigoryvp
@Auge der Hölle. Es sollte leicht sein. Dadurch wird versucht, ein Zeilenende gefolgt von einem Zeilenanfang abzugleichen. Was in einer Zeile unmöglich ist.
Nadia Alramli
1
Aber natürlich mit mehreren Zeilen möglich (abhängig davon, ob das Flag aktiviert ist) - eine Lösung, die funktioniert, ob das Flag aktiviert ist oder nicht, finden Sie in meiner Antwort.
Peter Boughton
16
Der reguläre Ausdruck "$ ^" stimmt zumindest in einigen Implementierungen mit der leeren Zeichenfolge überein. Der zweite ist besser.
Roman Starkov
@romkyns Zweitens stimmt die leere Zeichenfolge in meinem Aufruf von PyQt4 nicht überein QtCore.QRegExp. So schlimm, denn die Ausführung wäre sicherlich leichter gewesen.
Joël
43

(?!)sollte immer nicht übereinstimmen. Es ist der negative Ausblick mit der Breite Null. Wenn das, was in Klammern steht, übereinstimmt, schlägt die gesamte Übereinstimmung fehl. Da es nichts enthält, wird es das Match für nichts (einschließlich nichts) nicht bestehen.

Chas. Owens
quelle
4
Richtig, ich wollte das auch nur posten. Dies ist der beste Weg, wenn Ihre Sprache Lookaheads unterstützt. Ebenso (? =) Entspricht jeder Zeichenfolge.
Brian Carper
16

Um eine leere Zeichenfolge abzugleichen - auch im mehrzeiligen Modus - können Sie Folgendes verwenden \A\Z:

re.compile('\A\Z|\A\Z*|\A\Z+')

Der Unterschied besteht darin, dass \Aund \ZAnfang und Ende der Zeichenfolge sind , während ^und $diese mit dem Anfang / Ende der Zeilen$^|$^*|$^+ übereinstimmen können , sodass möglicherweise eine Zeichenfolge mit Zeilenumbrüchen übereinstimmen kann (wenn das Flag aktiviert ist).

Wenn Sie mit nichts übereinstimmen möchten (auch nicht mit einer leeren Zeichenfolge), versuchen Sie einfach, den Inhalt vor dem Beginn der Zeichenfolge zu finden, z.

re.compile('.\A|.\A*|.\A+')

Da (per Definition) keine Zeichen vor \ A stehen können, stimmt dies immer nicht überein.

Peter Boughton
quelle
Ihre sieht besser aus als meine, da ich davon ausgehe, dass sie schneller beendet wird als die Verwendung des Zeilenende.
ShuggyCoUk
Peter, du verwendest \ z (Kleinbuchstaben), während mein Python-Taschenführer mir sagt, dass die Aussage am Ende der Zeichenfolge \ Z (Großbuchstaben) ist?!
ThomasH
ThomasH, beide sind das Ende der Zeichenfolge, aber die Großbuchstabenversion erlaubt eine nachgestellte Zeilenumbruch, die Kleinbuchstaben nicht.
Peter Boughton
Mh, interessant, ich finde das nirgends dokumentiert. Außerdem gibt re.search ("boo \ z", "fooboo") kein Übereinstimmungsobjekt zurück, während re.search ("boo \ Z", "fooboo) dies tut. Stattdessen re.search (" boo \ z ") "," foobooz ") stimmt überein, was darauf hinweist , dass '\ z' einfach als 'z' interpretiert wird, oder?! (Dies ist in Python 2.6).
ThomasH
Tut mir leid, ich dachte, Python wäre PCRE, aber es stellt sich heraus, dass es einige Unterschiede gibt, und dies ist einer davon. (Siehe 'Anker' unter regulär-expressions.info / refflavors.html )
Peter Boughton
4

Vielleicht '.{0}'?

Steef
quelle
1

Sie könnten verwenden
\z..
Dies ist das absolute Ende der Zeichenfolge, gefolgt von zwei von allem

Wenn +oder *am Ende angeheftet wird, funktioniert dies immer noch und weigert sich, irgendetwas zu finden

ShuggyCoUk
quelle
Warum zwei von irgendetwas? Im Gegensatz dazu \zerlaubt das IIRC keine nachgestellten Zeilenumbrüche \Z, reicht also nicht aus? Oder dies ist eine seltsame Verteidigung gegen *(warum schützen Sie sich davor?)
mpen
0

Oder verwenden Sie ein Listenverständnis, um die nutzlosen regulären Ausdrücke zu entfernen, und verbinden Sie sie, um sie alle zusammenzufügen. Etwas wie:

re.compile('|'.join([x for x in [regexp1, regexp2, ...] if x != None]))

Achten Sie jedoch darauf, einige Kommentare neben dieser Codezeile hinzuzufügen :-)

Mike Miller
quelle