【问题标题】:Regex pattern for multi-episode file names多集文件名的正则表达式模式
【发布时间】:2014-06-22 01:43:13
【问题描述】:

我正在尝试编写一个正则表达式来从文件名中获取有关电视节目剧集的数据。

我将首先展示一些我正在处理的输入类型以及我希望如何输出数据的示例。

输入:

  • showname.s01e01e02e03.extension
  • showname.s01e01-02-03.extension

注意:剧集的数量可能会有所不同,但至少为 2。

输出:

  • 赛季编号,即 s01 中的“01”
  • 剧集编号,即 01e02e03 或 01-02-03

注意:如果可以使用正则表达式获取单独的剧集编号,那也很好 - 如果没有,我就将它们分开。

我的尝试:

我是not really that great with regular expressions,所以我目前的尝试可能很糟糕。无论如何,这是我到目前为止所得到的 - 显然不起作用:

(?i)s(?<season>\\d{1,4})(e(\\d{1,3})){2,}

我的想法是为季节编号创建一个组(这部分有效),然后尝试根据重复匹配剧集编号,但是,是的,现在是凌晨 3.41,我真的无法理解它。

一个完整的解决方案会很好,但任何想法或指针都非常感谢:-)

PS。如果接受的答案包含对正则表达式的解释,我将添加赏金以帮助我自己和其他人学习。

【问题讨论】:

    标签: java regex


    【解决方案1】:

    (我和你住在同一个时区,所以我的尝试也可能不准确,因为我睡着了,但我走了)

    如果我对您的理解正确(也在尝试分析您的正则表达式尝试)

    • sXXXXeXXXeXXXsXXXXeXXX-XXX 部分始终位于点之间
    • sXXXX只能存在一次,但可以有1-4位(这里用X表示),
    • 赛季信息后必须有eXXX 部分,并且至少是eXXX-XXX 表单中的元素之一(每个元素只能包含1-3 位数字)。

    在这种情况下,您可以使用像

    这样的正则表达式
    [.]s(?<season>\\d{1,4})e(?<episodes>\\d{1,3}([e-]\\d{1,3})+)[.]
    

    意思是

    • [.]点字面量

    • s(?&lt;season&gt;\\d{1,4}) 将匹配 sXXXX 并将其存储在名为 season 的组中

    • e 文字放在季节信息之后(从您的示例中似乎是强制性的)

    • (?&lt;episodes&gt;\\d{1,3}([e-]\\d{1,3})+) 在这种情况下

      • \\d{1,3} 将匹配 XXX
      • ([e-]\\d{1,3})+eXXX-XXX 中的至少一个。

      换句话说,它将匹配XXXeXXXXXX-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]
    -----
    

    【讨论】:

    • 非常感谢!是的,你从我的尝试中“提取”的东西是正确的。可能应该将其添加到问题中。无论如何,这是最接近我想要实现的答案,并且很容易修改它:-) 谢谢!
    • 会尽可能增加赏金。
    • @MichellBak 很高兴它对你有用。无论如何,您不需要添加赏金,因为这个问题没有那么具有挑战性(至少没有我回答的previous one 那么多)并且可能不会被许多其他人重用。你也很接近所以我没有改变你的正则表达式。
    • 哦,是的,你也回答了我的最后一个问题!正则表达式神! :-D
    • Nah,我对正则表达式的了解很好,但需要大量学习(和练习)才能成为像 this guy 这样的神。
    【解决方案2】:

    季节: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 组(季节)和更多文字字符
    • 对于情节字符串,我们不直接使用第 2 组(即m.group(2)),而是将所有e 字符替换为破折号:replace("e", "-")... 但仅在第一个字符之后开始,因为我们没有不想用破折号替换第一个em.group(2).substring(1,m.group(2).length())

    【讨论】:

    • FYI 添加了代码来显示如何获得这样的输出,没有e 在剧集之间:Season: 01 - Episodes: 01-02-03 如果您有任何问题,请告诉我。 :)
    • 非常感谢(双方)您的回答!虽然这确实回答了这个问题,但 Pshemo 的回答添加了一些我需要的额外内容(并且从我自己的尝试中可以看到)。很抱歉没有明确要求 - 来晚了:-/
    • explanation of the regex in order to help both myself and others learn. 所以...没有赏金? :)
    • 好吧,你真的不应该要求那种东西。无论如何,您引用的文字是指已接受的答案。我已经对此发表了评论,说我会提供赏金,Pshemo 说不需要,因为这个问题没有那么具有挑战性。
    • 感谢您的解释,但我仍然认为这是一个有效的问题。您确实在问题陈述中提到了赏金,这促使我花很多时间来详细回答。不管你接受了哪个答案,我很自然会好奇你在回答者面前悬而未决的最初激励发生了什么。至于我应该做什么,不应该做什么......对不起,但这不是你说的......那是我妻子的事!......哈哈
    【解决方案3】:

    也可以利用已经对剧集名称进行正则表达式匹配的其他任何人。例如,请参阅此页面,该页面讨论有关 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 只是一个起点。我会查找所有这些类似类型的软件包,看看他们最终决定使用什么正则表达式,因为他们已经花了很多心思。

    【讨论】:

    • 谢谢。我的应用实际上是 XBMC 的竞争对手,所以我宁愿不使用他们的代码库 :-) 此外,该部分不处理多集文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 1970-01-01
    • 2011-05-11
    • 2019-08-09
    • 1970-01-01
    相关资源
    最近更新 更多