Как я могу преобразовать регулярное выражение Perl с именованными группами в Python? - PullRequest
3 голосов
/ 27 июня 2009

Я пытаюсь преобразовать следующее регулярное выражение Perl, которое я нашел в модуле Perl Video :: Filename , в регулярное выражение Python 2.5.4 для синтаксического анализа имени файла

# 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>[^\/]+?))?$',

Я бы тоже хотел использовать именованные группы, и я знаю, что в Python расширение регулярных выражений для именованных групп отличается, но я не уверен на 100% в синтаксисе.

Вот что я попробовал:

# 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>[^\/]+?))?$')

Я получаю ошибку:

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

Например, этот мне удалось преобразовать, и он работает. Но тот, что выше, я не могу понять, правильно. Я получаю ошибку компиляции в 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>[^\/]+?))?$')

Я не уверен, с чего начать.

Ответы [ 4 ]

6 голосов
/ 27 июня 2009

Есть 2 проблемы с вашим переводом. Во-первых, второе упоминание openb содержит лишние скобки вокруг него, что делает его условным выражением , а не именованным выражением.

Далее, вы не перевели \k<season> обратную ссылку , Python использует (P=season) для совпадения. Следующие компиляции для меня:

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>[^\/]+?))?$')

На вашем месте я бы использовал re.VERBOSE, чтобы разбить это выражение на несколько строк и добавить обильную документацию, чтобы вы могли продолжать понимать выражение в будущем, если это что-то, что необходимо поддерживать, хотя.

(отредактировано после реализации второй ссылки openb, являющейся условным выражением и для правильного перевода обратной ссылки).

2 голосов
/ 27 июня 2009

Я нашел оскорбительную часть, но не могу понять, что именно не так, не обдумывая все это.

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>[^\/]+?))?$')

Похоже, проблема в том, что имена групп в python должны быть действительными идентификаторами python (см. документация ). Скобки, кажется, проблема. Удаление их дает

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

redefinition of group name 'openb' as group 6; was group 2
0 голосов
/ 27 июня 2009

Я могу ошибаться, но вы пытались получить обратную ссылку, используя:

(?:\k<season>x)

Не является ли синтаксис \g<name> в Python?

0 голосов
/ 27 июня 2009

Эти регулярные выражения - продукт больного и искаженного ума ...: -)

В любом случае, (? ()) - это условия как в Python, так и в Perl, и приведенный выше синтаксис perl выглядит так, как будто он должен совпадать с синтаксисом Python, т. Е. Он оценивается как true для указанной группы, существует.

С чего начать поиск? Документация по модулям находится здесь:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...