正则表达式 - 如何识别一个模式直到找到第二个模式

1 投票
3 回答
869 浏览
提问于 2025-04-17 07:29

我有一个文件,名字是特定的格式。比如说,它的名字是:

tv_show.s01e01.episode_name.avi

这是网络上电视节目集的标准命名方式。这个命名模式在网上几乎都是一样的,所以我想从这样命名的文件中提取一些信息。基本上,我想得到:

  1. 节目的标题;
  2. 季号 s01
  3. 集号 e01
  4. 文件扩展名。

我正在用Python 3脚本来实现这个功能。这个测试文件比较简单,因为我只需要这样做:

import re

def acquire_info(f="tv_show.s01e01.episode_name.avi"):
    tvshow_title = title_p.match(f).group()
    numbers = numbers_p.search(f).group()
    season_number = numbers.split("e")[0].split("s")[1]
    ep_number = numbers.split("e")[1]
    return [tvshow_title, season_number, ep_number]

if __name__ == '__main__':
    # re.I stands for the option "ignorecase"
    title_p = re.compile("^[a-z]+", re.I)
    numbers_p = re.compile("s\d{1,2}e\d{1,2}", re.I)
    print(acquire_info())

然后输出结果是我预期的 ['tv_show', '01', '01']。但是如果我的文件名是这样的呢? some.other.tv.show.s04e05.episode_name.avi

我该如何构建一个正则表达式,来获取所有在 "s\d{1,2}e\d{1,2}" 这个模式之前的文本呢?

顺便说一下,我没有在例子中放入获取扩展名的代码,我知道,但这不是我的问题,所以不重要。

3 个回答

0

我不是Python专家,但如果它可以进行命名捕获,像下面这样的一般写法可能会有效:

^(?<Title>.+)\.s(?<Season>\d{1,2})e(?<Episode>\d{1,2})\..*?(?<Extension>[^.]+)$

如果没有命名组,那就用普通的组。

一个问题可能会出现,如果标题中有一个 .s2e1. 的部分,这可能会遮盖真实的季和集信息。那就需要更多的逻辑来处理。上面的正则表达式假设标题、季、集和扩展名都存在,并且s/e是最右边的部分。

1

这里有一个方法,可以使用捕获组一次性提取你想要的所有信息:

>>> show_p = re.compile(r'(.*?)\.s(\d{1,2})e(\d{1,2})')
>>> show_p.match('some.other.tv.show.s04e05.episode_name.avi').groups()
('some.other.tv.show', '04', '05')
2

试试这个

show_p=re.compile("(.*)\.s(\d*)e(\d*)")
show_p.match(x).groups()

这里的 x 是你的字符串

编辑**(我忘了加上扩展名,这里是修正后的版本)

show_p=re.compile("^(.*)\.s(\d*)e(\d*).*?([^\.]*)$")
show_p.match(x).groups()

这是测试结果

>>> show_p=re.compile("(.*)\.s(\d*)e(\d*).*?([^\.]*)$")
>>> x="tv_show.s01e01.episode_name.avi"
>>> show_p.match(x).groups()
('tv_show', '01', '01', 'avi')
>>> x="tv_show.s2e1.episode_name.avi"
>>> show_p.match(x).groups()
('tv_show', '2', '1', 'avi')
>>> x='some.other.tv.show.s04e05.episode_name.avi'
>>> show_p.match(x).groups()
('some.other.tv.show', '04', '05', 'avi')
>>>  

撰写回答