我正在尝试编写正则表达式,以便从文件名中获取有关电视节目集的数据。
我首先展示一些我正在处理的输入以及我喜欢数据输出的例子。
输入:
注意:剧集数量可能会有所不同,但至少会有2集。
输出:
注意:如果可以使用正则表达式来获取个别剧集编号,那么这也很好 - 如果没有,我会将它们分开。 < / p>
我尝试过的事情:
我not really that great with regular expressions,所以我目前的尝试可能很糟糕。无论如何,这是我到目前为止所得到的 - 显然不起作用:
(?i)s(?<season>\\d{1,4})(e(\\d{1,3})){2,}
我的想法是为季节编号创建一个组(该部分有效),然后尝试根据重复匹配剧集编号,但是,它在这里是3.41 AM,我可以&#39;真的把头包住了。
一个完整的解决方案会很好,但任何想法或指示都非常感激: - )
PS。如果接受的答案包含对正则表达式的解释,以便帮助我和他人学习,我会添加一笔赏金。
答案 0 :(得分:1)
季节:01 - 集:01-02-03
底部的简单代码输出上面的字符串(如Java demo底部所示)。但是你说你想要一些解释,所以我们会一步一步地进行。
<强>一步步骤强>
让我们首先构建一个简单的正则表达式。然后我们会根据您的需求改进输出。
搜索: ^.*?s(\d{2})((?:e\d{2})+)\..*
替换: Season: $1 - Episodes: $2
输出: Season: 01 - Episodes: e01e02e03
在regex101 demo中,请参阅底部的替换。在下面的Java代码中,我们不会替换任何东西。这只是为了看看事情是如何运作的。
解释匹配
^
声称我们位于字符串的开头.*?
懒惰地匹配字符,最多...... s(\d{2})
匹配s
,然后括号将两位数字捕获到第1组((?:e\d{2})+)
中的外括号定义了捕获组2 (?:e\d{2})
匹配e
和两位数,+
量词确保我们这样做一次或多次,允许我们捕捉到第2组的所有剧集\.
与扩展名之前的时段匹配.*
匹配字符串的结尾解释替换
e
。Season:
写入文字字符Season:
$1
是对第1组的反向引用,并插入季节- Episodes:
插入文字字符- Episodes:
$2
是对第2组的反向引用,并插入剧集更进一步:剧集编号(或其他改进)之间的破折号
让我们说你想要Season: 01 - Episodes: 01-02-03
这在简单的正则表达式搜索中是不可能的,并且在文本编辑器中替换,但在编程语言中很容易使用匹配的捕获组来构建输出字符串。
以下是示例Java代码(请参阅online demo底部的输出):
String subject = "showname.s01e01e02e03.extension";
Pattern regex = Pattern.compile("^.*?s(\\d{2})((?:e\\d{2})+).*");
Matcher m = regex.matcher(subject);
String myoutput = "No Match"; // initialize
if (m.find()) {
myoutput = "Season: " + m.group(1) +" - Episodes: " ;
myoutput += m.group(2).substring(1,m.group(2).length()).replace("e", "-");
}
System.out.println(myoutput);
代码如何运作
myoutput = "Season: " + m.group(1) +" - Episodes: " ;
为我们提供了一些文字字符,第1组(季节)和更多文字字符m.group(2)
),而是使用短划线替换所有e
个字符:replace("e", "-")
...但仅在第一个字符串后面开始字符,因为我们不想用短划线替换第一个e
:m.group(2).substring(1,m.group(2).length())
答案 1 :(得分:1)
(我和你一样生活在同一个时区,所以我的尝试可能也不准确,因为我半睡半醒但是我走了)
如果我理解正确(也试图分析你的正则表达式尝试)
sXXXXeXXXeXXX
或sXXXXeXXX-XXX
始终位于点之间sXXXX
只能存在一次,但可以有1-4位数字(此处由X
表示),eXXX
部分,并且在eXXX
或-XXX
形式的元素之一(每个只能包含1-3个数字)。在这种情况下,您可以使用正则表达式
[.]s(?<season>\\d{1,4})e(?<episodes>\\d{1,3}([e-]\\d{1,3})+)[.]
表示
[.]
dot literal
s(?<season>\\d{1,4})
将匹配sXXXX
并将其存储在名为赛季的组中
e
字面意思(似乎是您的示例中必须的)
(?<episodes>\\d{1,3}([e-]\\d{1,3})+)
\\d{1,3}
将匹配XXX
([e-]\\d{1,3})+
以及此后eXXX
或-XXX
中的至少一个。换句话说,它会匹配XXXeXXX
,XXX-XXX
甚至是XXXeXXX-XXX
之类的内容,并将其放入名为episodes
[.]
点文字
如果您想要一些具有分隔的剧集列表的结构,那么您只需要从名为episodes
的组中拆分匹配。由于此匹配可以采用XXXeXXX-XXX
格式,因此您可以分为e
或-
,可以由正则表达式[e-]
或e|-
表示。
演示:
String[] data = {
"showname.s01e01e02e03.extension",
"showname.s01e01-02-03.extension",
};
Pattern p = Pattern.compile(
"[.]s(?<season>\\d{1,4})e(?<episodes>\\d{1,3}([e-]\\d{1,3})+)[.]",
Pattern.CASE_INSENSITIVE);
for (String input : data){
Matcher m = p.matcher(input);
while (m.find()){
String season = m.group("season");
System.out.println(season);
String episodes = m.group("episodes");
System.out.println(m.group("episodes"));
String[] singleEpisodes = episodes.split("[e-]");
System.out.println("episode numbers"+Arrays.toString(singleEpisodes));
}
System.out.println("-----");
}
输出:
01
01e02e03
episode numbers[01, 02, 03]
-----
01
01-02-03
episode numbers[01, 02, 03]
-----
答案 2 :(得分:0)
也可以利用其他已经完成剧集名称的正则表达式匹配的人。例如,请参阅此页面,其中讨论了有关XBMC以及它与剧集名称匹配的一些高级主题:
http://wiki.xbmc.org/index.php?title=Advancedsettings.xml#tvshowmatching
如果链接在将来变得陈旧,提到的一些事情是:
<tvshowmatching>
<regexp>[Ss]([0-9]+)[][ ._-]*[Ee]([0-9]+)([^\\/]*)$</regexp> <!-- foo.s01.e01, foo.s01_e01, S01E02 foo, S01 - E02 -->
<regexp>[\._ -]()[Ee][Pp]_?([0-9]+)([^\\/]*)$</regexp> <!-- foo.ep01, foo.EP_01 -->
<regexp>([0-9]{4})[\.-]([0-9]{2})[\.-]([0-9]{2})</regexp> <!-- foo.yyyy.mm.dd.* (byDate=true) -->
<regexp>([0-9]{2})[\.-]([0-9]{2})[\.-]([0-9]{4})</regexp> <!-- foo.mm.dd.yyyy.* (byDate=true) -->
<regexp>[\\/\._ \[\(-]([0-9]+)x([0-9]+)([^\\/]*)$</regexp> <!-- foo.1x09* or just /1x09* -->
<regexp>[\\/\._ -]([0-9]+)([0-9][0-9])([\._ -][^\\/]*)$</regexp> <!-- foo.103*, 103 foo -->
<regexp>[\/._ -]p(?:ar)?t[_. -]()([ivx]+)([._ -][^\/]*)$</regexp> <!-- Part I, Pt.VI -->
</tvshowmatching>
请注意,XBMC只是一个起点。我会查找所有相似类型的软件包,看看他们最终决定使用什么样的正则表达式,因为他们已经考虑了很多。