【问题标题】:How can I capture multiple matches for a sub-expression from a single string with Perl?如何使用 Perl 从单个字符串中捕获子表达式的多个匹配项?
【发布时间】:2014-11-20 03:12:26
【问题描述】:

我目前有以下正则表达式:

^\s*(.+)(?:[-\._ ]+)(\d+)\s*[xX]\s*(\d+)

这将匹配show_3x01_ep. name 并检索show301。我想扩展它,以便可以捕获多个剧集。例如:

 show _3x01_3x02 ep. name

应该返回:

show, 3, 01, 3, 02

有人可以向我解释一下这是怎么做到的吗?

【问题讨论】:

    标签: regex perl capture-group


    【解决方案1】:

    您对正则表达式的期望过高。最简单的方法是分两步完成。

    首先请注意,尽管在您的示例中匹配 show(.+) 过于笼统。如果您将模式应用于show _3x01_3x02 ep. name,那么您将得到show——带有尾随空格——因为以下[-._ ]+(无需转义点或将字符类括在(?: ... )中)是对一个字符感到满意。

    这将按照您的要求进行。它查找第一个字母字符字符串,然后查找由单个 x 分隔的所有数字字符串对。

    use strict;
    use warnings;
    
    my $s = 'show _3x01_3x02 ep. name';
    
    if ( my ($prefix) = $s =~ /([a-z]+)/i ) {
      print "$prefix\n";
      print "$1 $2\n" while $s =~ /(\d+)x(\d+)/g;
    }
    

    输出

    show
    3 01
    3 02
    

    【讨论】:

    • 感谢鲍罗丁。读完后,我决定从头开始,尝试简化。
    【解决方案2】:

    使用 Perl 的 g 修饰符

    您可以使用 Perl 的 g 正则表达式修饰符在字符串中多次扫描模式。然后,您可以将这些匹配项保存到列表中,然后对该列表或其各个元素执行某些操作。例如:

    $ echo 'show _3x01_3x02 ep.name' |
          perl -ne '@words = ($_ =~ /\A(.*?)(?=\d)|(\d+)x(\d+)/g);
                    @words = grep { $_ ne "" } @words;
                    while (my $idx = each @words) {
                        @words[$idx] =~ s/^\s+|\s+\b|_//g;
                    };
                    print join(", ", @words), "\n"'
    show, 3, 01, 3, 02
    

    【讨论】:

      【解决方案3】:

      在 Ruby 中使用 String#scan 代替

      您的文件名不一致,因此您最好扫描已知模式然后进行清理。我已经provided a Perl solution,但提供此 Ruby 解决方案作为替代方案。例如:

      str = 'show _3x01_3x02 ep. name'
      str.scan(/\A(.*?)(?=\d)|(\d+)x(\d+)/).
          flatten.compact.map { |e| e.gsub(?_, ' ').strip }
      #=> ["show", "3", "01", "3", "02"]
      

      在这一行代码中有很多内容,但应该很容易理解。代码将:

      1. 匹配从字符串开头到第一个数字的所有内容作为节目名称。
      2. 匹配它可以找到的所有季节/剧集对。
      3. 以数组形式返回所有匹配项。
      4. 扁平化由捕获组创建的嵌套数组,并丢弃 nil。
      5. 在数组的每个成员中用空格替换下划线。
      6. 从数组的每个成员中去除任何周围的空白。
      7. 返回数组。

      正则表达式本身与 Perl 兼容,但其余逻辑依赖于 Ruby 的 String#scan 和其他可能无法直接映射到 Perl 的内部结构。 YMMV。

      【讨论】:

        猜你喜欢
        • 2011-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-11
        • 2012-05-04
        • 1970-01-01
        相关资源
        最近更新 更多