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

如何将带有命名组的Perl正则表达式转换为Python?,python,regex,perl,Python,Regex,Perl,我试图将在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}))?(?(<ope

我试图将在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中遇到一个编译错误

# 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>[^\/]+?))?$')
#Perl:
(3)s.s.赛赛赛斯(12)赛季系列)[\s..........................................................((((({1,2{1,2}[1,2}[1.2})[[x \[x \/\3.s.............................................................................................................................部分)[\s.\u]?(?\d+)(?[a-z])?(?:[\/\s.\u-]*(?[^\/]+)?$”,
#Python(工作模式):
(s)s.s.SE124;SE124;赛季;季节;系列))[\s.s....r.再。r.再.重新.编译(r)再.编译(r::::::((P:::::(,(r:::::(P\d{1,2}[P\d{1,2}[P\d{{1,2}[1,2}[P\d{[1,2}[P\1,2}[P\d{[1,2}[1.2}[P\d[x\\\/\0.s..........................................................................................(?:P | part)[\s.\u]?(?P\d+))(?P[a-z])?(?:[\/\s.\u-]*(?P[^\/]+)?$)

我不知道该从哪里开始寻找。

那些regexp是一个病态的扭曲思维的产物…:-)

无论如何,(?())在Python和Perl中都是条件,上面的Perl语法看起来应该与Python语法相同,即,对于名为exists的组,它的计算结果为true

从哪里开始寻找?模块的文档如下所示:


我发现了令人不快的地方,但如果不把注意力集中在整件事上,我就无法找出到底是哪里出了问题

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>[^\/]+?))?$')
r=re.compile(r'^(?(?P.*?[\/\s.-]*)?(?P\[)?(?P\d{1,2})[x\/](?P\d{1,2})(?:-(?:\kPx)(?P\d{1,2}))?
(?(P)\])//此处的此部分导致错误消息
(?:[\s.-]*(?P[^\/]+?)?$)
问题似乎在于python中的组名必须是有效的python标识符(检查)。括号似乎是问题所在。移除它们会使

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

redefinition of group name 'openb' as group 6; was group 2
(?(P)\])//带括号
(?P\])//不带括号
将组名“openb”重新定义为组6;是第2组

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

接下来,您没有翻译
\k
,Python使用
(p=seasure)
来匹配相同的代码。以下内容为我编写:

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>[^\/]+?))?$')
r=re.compile(r'^(?(?P.*)[\/\s.-]*)?(?P\[)(?P\d{1,2})[x\/](?P\d{1,2})(?:-(?:(?P=季节)x)(?P\d{1,2}))?(?(openb)\](?:[\s.[\d{1,2}*(?P.-/+))$)
如果我是你,我会使用re.VERBOSE将这个表达式拆分成多行,并添加丰富的文档,这样,如果这个表达式需要保持可维护性,那么你将来可以继续理解它


(在意识到第二个
openb
引用是一个条件表达式后编辑,并正确翻译反向引用)。

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

(?:\k<season>x)
(?:\kx)

Python中的语法不是
\g
吗?

读别人的正则表达式总是让我头疼。也许我最好还是用Python重写它们。不幸的是,它们使用的是regex扩展,这两种实现之间存在差异,因此无法一字不差地工作。我希望这里的某个地方有一位专家能够向我展示这两方面的差异。是的,我也做到了这一点,我认为这是因为Python希望一个命名组是(?P…),而语法不匹配,但我不知道该放在什么位置嗯,在Perl中\k表示对先前定义的命名组的反向引用,所以这是正常的(在本例中)在同一个正则表达式中有两个名称。啊,我明白了。然后需要转换为(?P=name)参考,我认为。更新..好吧,由于perlre手册页完全没有提到命名模式,也没有对它们的反向引用,而且我现在时间很短,我们现在把它作为读者的练习。实际上perlre<>提到命名模式和命名反向引用,但只在Perl5.10和更新版本上。对!现在我看到了t我断言openb被使用了两次也是不正确的;这是一个条件开关
(?(条件)yes模式| no模式)
,我们的提问者误译了。相应地更新我的答案。
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>[^\/]+?))?$')
(?:\k<season>x)