Was ist die Python-Art, eine \ G-verankerte Parsing-Schleife zu machen?

8

Was folgt, ist eine Perl-Funktion, die ich vor Jahren geschrieben habe. Es ist ein intelligenter Tokenizer, der einige Fälle von zusammenhängenden Dingen erkennt, die vielleicht nicht sein sollten. Zum Beispiel teilt die Eingabe auf der linken Seite die Zeichenfolge wie rechts gezeigt:

%Vor%

Ich mache jetzt ein maschinelles Lernexperiment, und ich möchte einige Experimente machen, die diesen Tokenizer verwenden. Aber zuerst muss ich es von Perl nach Python portieren. Der Schlüssel zu diesem Code ist die Schleife, die den \ G-Anker verwendet, etwas, von dem ich höre, dass es in Python nicht existiert. Ich habe versucht zu googeln, wie dies in Python gemacht wird, aber ich bin mir nicht sicher, nach was genau zu suchen, also habe ich Probleme, eine Antwort zu finden.

Wie würden Sie diese Funktion in Python schreiben?

%Vor%

Ich habe versucht, re.split () mit einer Variation der oben genannten zu verwenden. Split () verweigert jedoch die Aufteilung auf eine Null-Breite-Übereinstimmung (eine Fähigkeit, die möglich sein sollte, wenn man wirklich weiß, was man tut).

Ich habe eine Lösung für dieses spezielle Problem gefunden, aber nicht für das allgemeine Problem "Wie benutze ich \ G basierend auf Parsing" - Ich habe einen Beispielcode, der in Schleifen, die mit \ G und dann verwendet es im Körper eine andere Übereinstimmung, die bei \ G verankert ist, um zu sehen, wie mit der Syntaxanalyse verfahren werden soll. Ich suche also immer noch nach einer Antwort.

Das heißt, hier ist mein letzter Arbeitscode für die Übersetzung des oben genannten zu Python:

%Vor%     
John Arrowwood 06.12.2015, 19:35
quelle

1 Antwort

2

Emulieren \G am Anfang einer Regex mit re.RegexObject.match

Sie können den Effekt von \G am Anfang einer Regex mit re Modul emulieren, indem Sie re.RegexObject.match , wodurch das Match an der angegebenen Position in pos beginnt.

%Vor%

Vorbehalt

Ein Nachteil dieser Methode besteht darin, dass sie nicht gut mit Regex funktioniert, die mit der leeren Zeichenfolge in der Hauptübereinstimmung übereinstimmt, da Python keine Möglichkeit hat, die Regex zu zwingen, die Übereinstimmung erneut zu versuchen, während die Übereinstimmung der Länge Null verhindert wird.

Als ein Beispiel gibt re.findall(r'(.??)', 'abc') ein Array von 4 leeren Strings ['', '', '', ''] zurück, während in PCRE 7 Übereinstimmungen ['', 'a', '', 'b', '', 'c' ''] gefunden werden, wobei die 2., 4. und 6. Übereinstimmung mit den gleichen Indizes wie die 1. beginnen , 3. und 5. Spiele jeweils. Die zusätzlichen Übereinstimmungen in PCRE werden gefunden, indem dieselben Indizes mit einem Flag wiederholt werden, das eine leere Zeichenfolge verhindert.

Ich weiß, dass die Frage Perl ist, nicht PCRE, aber das globale Matching-Verhalten sollte dasselbe sein. Sonst hätte der ursprüngliche Code nicht funktioniert.

Das Umschreiben von ([^a-zA-Z0-9]*)([a-zA-Z0-9]*?) in (.+?) , wie in der Frage ausgeführt, vermeidet dieses Problem, obwohl Sie möglicherweise re.S Flagge.

Andere Kommentare zur Regex

Da die Groß- und Kleinschreibung in Python das gesamte Muster betrifft, müssen die Groß- und Kleinschreibung nicht beachtet werden. Ich würde (?i:st) als [sS][tT] umschreiben, um die ursprüngliche Bedeutung beizubehalten, aber gehen Sie mit (?:st|ST) , wenn es Teil Ihrer Anforderung ist.

Da Python den Modus für freie Abstände mit re.X -Flag unterstützt, können Sie kann Ihre Regex ähnlich wie in Perl-Code schreiben:

%Vor%     
nhahtdh 07.12.2015 05:15
quelle

Tags und Links