确保分组匹配不以特定字符结尾的正则表达式

1 投票
5 回答
2451 浏览
提问于 2025-04-15 22:54

我在写一个正则表达式的时候遇到了一些麻烦,想要匹配特定的情况。我有一份电视节目名称的列表,大概有四种格式:

  • 节目名称.S01E01
  • 节目名称.0101
  • 节目名称.01x01
  • 节目名称.101

我想要匹配的是节目的名称。我的主要问题是,我的正则表达式匹配到的节目名称前面总是有一个点(.)。我的正则表达式如下:

"^([0-9a-zA-Z\.]+)(S[0-9]{2}E[0-9]{2}|[0-9]{4}|[0-9]{2}x[0-9]{2}|[0-9]{3})"

一些例子:

>>> import re

>>> SHOW_INFO = re.compile("^([0-9a-zA-Z\.]+)(S[0-9]{2}E[0-9]{2}|[0-9]{4}|[0-9]{2}x[0-9]{2}|[0-9]{3})")
>>> match = SHOW_INFO.match("Name.Of.Show.S01E01")
>>> match.groups()
('Name.Of.Show.', 'S01E01')
>>> match = SHOW_INFO.match("Name.Of.Show.0101")
>>> match.groups()
('Name.Of.Show.0', '101')
>>> match = SHOW_INFO.match("Name.Of.Show.01x01")
>>> match.groups()
('Name.Of.Show.', '01x01')
>>> match = SHOW_INFO.match("Name.Of.Show.101")
>>> match.groups()
('Name.Of.Show.', '101')

所以我的问题是,如何避免第一个分组以一个点结束呢?我意识到我可以简单地这样做:

var.strip(".")

但是,这样做并不能处理“节目名称.0101”的情况。我有没有办法改进这个正则表达式,让它更好地处理这种情况呢?

提前谢谢你。

5 个回答

0

我觉得这个方法可以满足你的需求:

^([0-9a-z\.]+)\.(?:S[0-9]{2}E[0-9]{2}|[0-9]{3,4}|[0-9]{2}(?:x[0-9]+)?)$

我用下面这几个节目名称测试过:

  • 30.Rock.S01E01
  • The.Office.0101
  • Lost.01x01
  • How.I.Met.Your.Mother.101

如果这四个例子能代表你手头的文件类型,那么这个正则表达式应该能把节目名称单独提取出来,其他的部分就会被忽略掉。这个过滤器可能比其他一些更严格,但我个人比较喜欢精确匹配你所需要的内容。

1

所以最后一组的唯一限制就是不能包含点号?这很简单:

^(.*?)(\.[^.]+)$

这个匹配任何东西,但不是贪婪地匹配。关键在于第二组,它是以点号开头,然后匹配任何不是点号的字符,一直到字符串的末尾。

这样做可以适用于你所有的测试案例。

1

我觉得这样做就可以了:

>>> regex = re.compile(r'^([0-9a-z.]+)\.(S[0-9]{2}E[0-9]{2}|[0-9]{3,4}|[0-9]{2}x[0-9]{2})$', re.I)
>>> regex.match('Name.Of.Show.01x01').groups()
('Name.Of.Show', '01x01')
>>> regex.match('Name.Of.Show.101').groups()
('Name.Of.Show', '101')

预计完成时间: 当然,如果你只是想从可信的字符串中提取不同的部分,你可以直接使用字符串的方法:

>>> 'Name.Of.Show.101'.rpartition('.')
('Name.Of.Show', '.', '101')

撰写回答