如何将具有命名组的Perl正则表达式转换为Python?

时间:2009-06-27 14:40:28

标签: python regex perl

我正在尝试将我在Video::Filename Perl模块中找到的以下Perl正则表达式转换为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 个答案:

答案 0 :(得分:6)

您的翻译有两个问题。首先,第二次提到openb时会有额外的括号,使其成为conditional expression,而不是命名表达式。

接下来是您没有翻译\k<season> backreference,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引用后编辑是条件表达式,并正确翻译反向引用)。

答案 1 :(得分:2)

我找到了令人讨厌的部分,但是如果不把整个事情包裹起来,就无法弄清楚到底出了什么问题。

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标识符(check documentation)。括号似乎是问题所在。删除它们

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

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

答案 2 :(得分:0)

那些正面试图是生病扭曲的心灵的产物......: - )

无论如何,(?())是Python和Perl中的条件,并且上面的perl语法看起来应该与Python语法相同,即它评估为名为exists的组的true。

从哪里开始寻找?这些模块的文档在这里:

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

答案 3 :(得分:0)

我可能错了,但您尝试使用以下方法进行反向引用:

(?:\k<season>x)

Python中的语法\g<name>不是吗?