有没有办法多次匹配模式(e\d\d
),将每个模式捕获到一个组中?例如,给定字符串..
blah.s01e24e25
..我希望得到四组:
1 -> blah
2 -> 01
3 -> 24
4 -> 25
使用的显式正则表达式是(在Python正则表达式中:
import re
re.match("(\w+).s(\d+)e(\d+)e(\d+)", "blah.s01e24e25").groups()
..但我也希望匹配以下任何一种:
blah.s01e24
blah.s01e24e25e26
您似乎无法做(e\d\d)+
,或者更确切地说,您可以,但它只捕获最后一次出现:
>>> re.match("(\w+).s(\d+)(e\d\d){2}", "blah.s01e24e25e26").groups()
('blah', '01', 'e25')
>>> re.match("(\w+).s(\d+)(e\d\d){3}", "blah.s01e24e25e26").groups()
('blah', '01', 'e26')
我想在单个正则表达式中执行此操作,因为我有多个模式来匹配电视剧集文件名,并且不希望复制每个表达式来处理多个剧集:
\w+\.s(\d+)\.e(\d+) # matches blah.s01e01
\w+\.s(\d+)\.e(\d+)\.e(\d+) # matches blah.s01e01e02
\w+\.s(\d+)\.e(\d+)\.e(\d+)\.e(\d+) # matches blah.s01e01e02e03
\w - \d+x\d+ # matches blah - 01x01
\w - \d+x\d+\d+ # matches blah - 01x01x02
\w - \d+x\d+\d+\d+ # matches blah - 01x01x02x03
......以及其他许多模式。
使问题复杂化的另一件事 - 我希望将这些正则表达式存储在配置文件中,因此不需要使用多个正则表达式和函数调用的解决方案 - 但如果这证明不可能,我将只允许用户添加简单的正则表达式< / p>
基本上,有没有办法使用正则表达式捕获重复模式?
答案 0 :(得分:5)
分两步完成,一个用于查找所有数字,一个用于分割它们:
import re
def get_pieces(s):
# Error checking omitted!
whole_match = re.search(r'\w+\.(s\d+(?:e\d+)+)', s)
return re.findall(r'\d+', whole_match.group(1))
print get_pieces(r"blah.s01e01")
print get_pieces(r"blah.s01e01e02")
print get_pieces(r"blah.s01e01e02e03")
# prints:
# ['01', '01']
# ['01', '01', '02']
# ['01', '01', '02', '03']
答案 1 :(得分:1)
捕获的组数等于括号组的数量。请查看findall
或finditer
以解决您的问题。
答案 2 :(得分:1)
非分组括号:(?:asdfasdf)
不必出现:(?:asdfasdf)?
c = re.compile(r"""(\w+).s(\d+)
(?:
e(\d+)
(?:
e(\d+)
)?
)?
""", re.X)
或
c = re.compile(r"""(\w+).s(\d+)(?:e(\d+)(?:e(\d+))?)?""", re.X)
答案 3 :(得分:0)
在考虑了这个问题之后,我想我有一个更简单的解决方案,使用命名组。
用户(或我)可以使用的最简单的正则表达式是:
(\w+\).s(\d+)\.e(\d+)
文件名解析类将第一组作为节目名称,第二组作为季节编号,第三组作为剧集编号。这涵盖了大多数文件。
我将允许一些不同的命名组:
(?P<showname>\w+\).s(?P<seasonnumber>\d+)\.e(?P<episodenumber>\d+)
为支持多集,我会支持两个命名群组,例如startingepisodenumber
和endingepisodenumber
来支持showname.s01e01-03
之类的内容:
(?P<showname>\w+\)\.s(?P<seasonnumber>\d+)\.e(?P<startingepisodenumber>\d+)-(?P<endingepisodenumber>e\d+)
最后,允许名称与episodenumber\d+
episodenumber1
,episodenumber2
等匹配的名称组:
(?P<showname>\w+\)\.
s(?P<seasonnumber>\d+)\.
e(?P<episodenumber1>\d+)
e(?P<episodenumber2>\d+)
e(?P<episodenumber3>\d+)
它仍然需要复制不同数量e01
s的模式,但永远不会有一个包含两个非连续剧集的文件(如show.s01e01e03e04
),所以使用{{1} }群组应该解决这个问题,对于用户遇到的奇怪案例,他们可以使用starting/endingepisodenumber
群组名称
这并没有真正回答模式序列问题,但它解决了导致我问这个问题的问题! (我仍会接受另一个答案,说明如何在一个正则表达式中匹配episodenumber\d+
- 如果有人解决了这个问题!)
答案 4 :(得分:0)
也许是这样的?
def episode_matcher(filename):
m1= re.match(r"(?i)(.*?)\.s(\d+)((?:e\d+)+)", filename)
if m1:
m2= re.findall(r"\d+", m1.group(3))
return m1.group(1), m1.group(2), m2
# auto return None here
>>> episode_matcher("blah.s01e02")
('blah', '01', ['02'])
>>> episode_matcher("blah.S01e02E03")
('blah', '01', ['02', '03'])