Python正则表达式可选捕获组
我遇到了一个问题,想从像这样的文件名中提取需要的数据:
miniseries.season 1.part 5.720p.avi
miniseries.part 5.720p.avi
miniseries.part VII.720p.avi # episode or season expressed in Roman numerals
文件名中可能会有“season XX”这一部分,也可能没有,或者它可能以简写的形式出现,比如“s 1”或“seas 1”。
无论如何,我希望能得到四个捕获组,输出结果如下:
group1 : miniseries
group2 : 1 (or None)
group3 : 5
group4 : 720p.avi
为此,我写了一个正则表达式:
(^.*)\Ws[eason ]*(\d{1,2}|[ivxlcdm]{1,5})\Wp[art ]*(\d{1,2}|[ivxlcdm]{1,5})\W(.*$)
这个正则表达式只在我有完整的文件名时有效,包括可选的“season XX”字符串。如果“season”没有找到,能否写一个正则表达式让第二组返回“None”?
1 个回答
66
让季节部分变成可选的其实很简单:
(^.*?)(?:\Ws(?:eason )?(\d{1,2}|[ivxlcdm]{1,5}))?\Wp(?:art )?(\d{1,2}|[ivxlcdm]{1,5})\W(.*$)
我们可以使用一种叫做非捕获组的东西((?:...)
),再加上一个表示“0次或1次”的符号(?
)。我还需要把第一个组设置为非贪婪模式,这样它就不会去匹配名字中的season
部分。
另外,我把eason
和art
这两个可选的字符串也改成了非捕获的可选组,而不是字符类。
结果是:
>>> import re
>>> p=re.compile(r'(^.*?)(?:\Ws(?:eason )?(\d{1,2}|[ivxlcdm]{1,5}))?\Wp(?:art )?(\d{1,2}|[ivxlcdm]{1,5})\W(.*$)', re.I)
>>> p.search('miniseries.season 1.part 5.720p.avi').groups()
('miniseries', '1', '5', '720p.avi')
>>> p.search('miniseries.part 5.720p.avi').groups()
('miniseries', None, '5', '720p.avi')
>>> p.search('miniseries.part VII.720p.avi').groups()
('miniseries', None, 'VII', '720p.avi')