确保分组匹配不以特定字符结尾的正则表达式
我在写一个正则表达式的时候遇到了一些麻烦,想要匹配特定的情况。我有一份电视节目名称的列表,大概有四种格式:
- 节目名称.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')