代码之家  ›  专栏  ›  技术社区  ›  Håkon Hægland

简化正则表达式以捕获重复的子组

  •  0
  • Håkon Hægland  · 技术社区  · 6 年前

    my $str = "1 2 3 4 ;";
    $str =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+/;
    print Dumper( [$1, $2, $3, $4] );
    

    输出 :

    $VAR1 = [
              '1',
              '2',
              '3',
              '4'
            ];
    

    $str =~ /(?:(\d+)\s+){4}/;
    

    但它给出了:

    $VAR1 = [
              '4',
              undef,
              undef,
              undef
            ];
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Schwern    6 年前

    是的,使用 /g 匹配所有数字。

    my @matches = $str =~ /\d+/g
    

    split 在空白和 filter 对于数字。

    grep /\d+/, split /\s+/, $str;
    

    $str =~ /(?:(\d+)\s+){4}/; 不起作用,因为 {4} \d+\s+ ,它不会改变只有一个捕获组。

        2
  •  1
  •   The fourth bird    6 年前

    如果要按编号分组,则必须像以前那样创建它们。

    (?:(\d+)\s+){4} 将重复外部组4次,仅捕获组1中最后一次迭代的值。


    \G 得到组1中的所有数字。

    \G(\d+)\h+(?=[\d\h]*;)
    

    • \G
    • (\d+)\h+ 捕获组1,捕获1+个数字并匹配1+个水平空白字符
    • (?= 积极向前看,断言右边的是
      • [\d\h]*;
    • ) 近距离展望

    Regex demo

    例如

    my $str = "1 2 3 4 ;";
    while ($str =~ /\G(\d+)\h+(?=[\d\h]*;)/g) {
        print "$1\n";
    }
    

    1
    2
    3
    4