2009-06-27 8 views
3

Ich versuche, die folgende Perl regex ich im Video::Filename Perl-Modul zu einem Python 2.5.4 regex, einen Dateinamen zu analysieren gefunden zu konvertierenWie kann ich einen Perl-Regex mit benannten Gruppen in Python konvertieren?

# Perl > v5.10 
re => '^(?:(?<name>.*?)[\/\s._-]*)?(?<openb>\[)?(?<season>\d{1,2})[x\/](?<episode>\d{1,2})(?:-(?:\k<season>x)?(?<endep>\d{1,2}))?(?(<openb>)\])(?:[\s._-]*(?<epname>[^\/]+?))?$', 

Ich mag würde zu benannten Gruppen verwenden, und ich weiß, in Python Die Regex-Erweiterung für benannte Gruppen ist anders, aber ich bin mir nicht 100% ig sicher in der Syntax. Diese

ist, was ich versucht:

# Python (not working) 
r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]*)?(?P<openb>\[)?(?P<season>\d{1,2})[x\/](?P<episode>\d{1,2})(?:-(?:\kP<season>x)?(?P<endep>\d{1,2}))?(?(P<openb>)\])(?:[\s._-]*(?P<epname>[^\/]+?))?$') 

Der Fehler erhalte ich:

raise error, v # invalid expression 
sre_constants.error: bad character in group name 

Zum Beispiel diese, die ich konvertieren verwaltet und es funktioniert. Aber das obige kann ich nicht richtig verstehen. Ich erhalte einen Kompilierungsfehler in Python.

# Perl: 
re => '^(?:(?<name>.*?)[\/\s._-]+)?(?:s|se|season|series)[\s._-]?(?<season>\d{1,2})[x\/\s._-]*(?:e|ep|episode|[\/\s._-]+)[\s._-]?(?<episode>\d{1,2})(?:-?(?:(?:e|ep)[\s._]*)?(?<endep>\d{1,2}))?(?:[\s._]?(?:p|part)[\s._]?(?<part>\d+))?(?<subep>[a-z])?(?:[\/\s._-]*(?<epname>[^\/]+?))?$', 

# Python (working): 
r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]+)?(?:s|se|season|series)[\s._-]?(?P<season>\d{1,2})[x\/\s._-]*(?:e|ep|episode|[\/\s._-]+)[\s._-]?(?P<episode>\d{1,2})(?:-?(?:(?:e|ep)[\s._]*)?(?P<endep>\d{1,2}))?(?:[\s._]?(?:p|part)[\s._]?(?P<part>\d+))?(?P<subep>[a-z])?(?:[\/\s._-]*(?P<epname>[^\/]+?))?$') 

Ich bin mir nicht sicher, wo ich anfangen soll.

Antwort

6

Es gibt 2 Probleme mit Ihrer Übersetzung. Vor allem hat die zweite Erwähnung von openb zusätzliche Klammern um es macht es zu einem conditional expression, nicht ein benannter Ausdruck.

Als nächstes haben Sie die \k<season>backreference nicht übersetzt, Python verwendet (P=season), um dasselbe zu erreichen. Im Folgenden stellt für mich:

r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]*)?(?P<openb>\[)?(?P<season>\d{1,2})[x\/](?P<episode>\d{1,2})(?:-(?:(?P=season)x)?(?P<endep>\d{1,2}))?(?(openb)\])(?:[\s._-]*(?P<epname>[^\/]+?))?$') 

Wenn ich Sie wäre, würde ich re.VERBOSE verwenden diesen Ausdruck über mehrere Zeilen aufgeteilt und reichlich Dokumentation hinzufügen, damit Sie den Ausdruck in der Zukunft zu verstehen, halten kann, wenn dies etwas ist, das muss jedoch wartbar bleiben.

(bearbeitet nach der Realisierung der zweiten openb Referenz war ein bedingter Ausdruck, und die Rückreferenz richtig zu übersetzen).

+1

Hmm In Perl bedeutet \ k eine Rückreferenz zu einer zuvor definierten benannten Gruppe, daher ist es normal (in diesem Fall), den Namen zweimal in derselben Regex zu haben. –

+0

Ah, ich verstehe. Dann muss das in eine (? P = Name) Referenz umgewandelt werden, denke ich. Aktualisieren .. –

+0

Nun, da die perlre man-Seite vollständig keine benannten Muster oder Rückreferenzen zu ihnen erwähnt, und ich momentan knapp bei der Zeit bin, werden wir das als eine Übung für den Leser für jetzt lassen. –

0

Diese regexps sind das Produkt eines kranken einem verdrehten Verstand ... :-)

Wie auch immer, (?()) Sind die Bedingungen in den beiden Python und Perl, und die Perl-Syntax sieht oben, wie es sein sollte das gleiche wie die Python-Syntax, dh es wird als wahr der Gruppe namens exists ausgewertet.

Wohin mit der Suche? Die Dokumentation für die Module sind hier:

http://docs.python.org/library/re.html http://www.perl.com/doc/manual/html/pod/perlre.html

+0

Die Regex von jemand anderem zu lesen, macht mir immer weh. Vielleicht ist es besser, sie einfach in Python neu zu schreiben. –

+0

Leider verwenden sie Regex-Erweiterungen, die zwischen den beiden Implementierungen unterscheiden, so dass es nicht wörtlich funktioniert. Ich hatte gehofft, irgendwo hier ist ein Experte, der mir die Unterschiede zeigen könnte. –

2

ich der säumige Teil gefunden, aber kann nicht herausfinden, was genau falsch ist meiner Meinung nach um die ganze Sache ohne Verpackung.

r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]*)?(?P<openb>\[)?(?P<season>\d{1,2})[x\/](?P<episode>\d{1,2})(?:-(?:\kP<season>x)?(?P<endep>\d{1,2}))? 

(?(P<openb>)\]) // this part here causes the error message 

(?:[\s._-]*(?P<epname>[^\/]+?))?$') 

Das Problem scheint mit der Tatsache, dass Gruppennamen in Python zu sein, müssen gültige Python-IDs (überprüfen documentation) sein. Die Klammern scheinen das Problem zu sein. Entfernen sie gibt

(?(P<openb>)\]) //with parentheses 
(?P<openb>\]) //without parentheses 

redefinition of group name 'openb' as group 6; was group 2 
+0

Ja, das habe ich auch so verstanden, weil Python eine benannte Gruppe erwartet (? P ...) und dass die Syntax nicht übereinstimmt, aber ich weiß nicht, was ich an ihrer Stelle einfügen soll –

0

ich falsch sein kann, aber Sie haben versucht, die Rückreferenzierung mit zu bekommen:

(?:\k<season>x) 

Ist nicht die Syntax \g<name> in Python?

Verwandte Themen