代码之家  ›  专栏  ›  技术社区  ›  con

Perl的捕获组在作用域中消失

  •  0
  • con  · 技术社区  · 1 年前

    我有一个非常简单的代码来解析文件名:

    #!/usr/bin/env perl
    
    use 5.040;
    use warnings FATAL => 'all';
    use autodie ':default';
    
    my $string = '/home/con/bio.data/blastdb/phytophthora.infestans.KR_2_A2/GCA_012552325.1.protein.faa';
    
    if ($string =~ m/blastdb\/(\w)\w+\.([\w\.]+)/) {
        my $rest = $2; # $1 would be valid here
        $rest =~ s/\./ /g;
        my $name = "$1.$rest"; # $1 disappears here
    }
    

    上面的代码以失败 Use of uninitialized value $1 in concatenation (.) or string

    但是,如果我保存 $1 转换为变量,例如。 $g ,信息没有丢失。

    if ($string =~ m/blastdb\/(\w)\w+\.([\w\.]+)/) {
        my ($g, $rest) = ($1, $2);
        $rest =~ s/\./ /g;
        my $name = "$g.$rest";
    }
    

    所以我 可以 解决这个问题。

    然而 1. 不应该就这样消失,不应该 1. 在范围内保持有效?这是Perl中的一个错误吗?或者有什么规则吗 https://perldoc.perl.org/perlretut 我错过了什么?

    1 回复  |  直到 1 年前
        1
  •  4
  •   hobbs    1 年前

    $rest =~ s/\./ /g; 进行正则表达式匹配。它匹配的模式( /\./ )没有任何捕获组,因此所有捕获变量在完成后都未初始化。

    您可以最简单地在变量中保存所需内容,方法是: if (my ($g, $rest) = $string =~ /yadda yadda/) 或者,在这种情况下,您可以避免在完成前一次捕获之前进行其他regex匹配, $rest =~ tr/./ / 会做得同样好 $rest =~ s/\./ /g ,但不会破坏捕获变量。