代码之家  ›  专栏  ›  技术社区  ›  Hielke Walinga

Perl Diamond运算符处于双循环挂起状态

  •  -1
  • Hielke Walinga  · 技术社区  · 6 年前

    在Perl脚本中,我有一个双无限while循环。我和钻石接线员一起从文件中读出行。但是如果我的脚本到达文件的最后一行,它不会返回UNdef,而是永久挂起。

    如果我将代码简化为一个while循环,则不会发生这种情况。所以我想知道我是否做错了什么,或者这是语言的一个已知限制。(这实际上是我的第一个Perl脚本。)

    下面是我的剧本。它的目的是计算fasta文件中DNA序列的大小,但是挂起行为可以用任何其他具有多行文本的文件观察到。

    Perl版本5.18.2

    从命令行调用 perl script.pl file.fa

    $l = <>;
    while (1) {
        $N = 0;
        while (1) {
            print "Get line";
            $l = <>;
            print "Got line";
            if (not($l)) {
                last;
            }
            if ($l =~ /^>/) {
                last;
            }
    
            $N += length($l);
        }
        print $N;
        if (not($N)) {
            last;
        }
    }
    

    我放置了一些调试打印语句,以便您可以看到最后一行是“get line”,然后挂起。

    1 回复  |  直到 6 年前
        1
  •  3
  •   lod    6 年前

    欢迎使用Perl。

    您的代码的问题是您无法从外部循环中逃脱。 <> 将返回 undef 当它到达文件末尾时。此时,内部循环结束,外部循环将其送回。强制进一步读取原因 <> 开始看 STDIN 它从不发送EOF,所以您的循环将永远持续下去。

    由于这是您的第一个Perl脚本,我将用一些注释为您重写它。Perl是一种非常好的语言,您可以编写一些很好的代码,但是大多数情况下,由于它的年代久远,有些旧的样式不再被建议使用。

    use warnings; # Warn about coding errors
    use strict; # Enforce good style
    use 5.010; # Enable modernish (10 year old) features
    
    # Another option which mostly does the same as above.
    # I normally do this, but it does require a non-standard CPAN library
    # use Modern::Perl;
    
    # Much better style to have the condition in the while loop
    # Much clearer than having an infinite loop with break/last statements
    # Also avoid $l as a variable name, it looks too much like $1
    my $count = 0; # Note variable declaration, enforced by strict
    while(my $line = <>) {
        if ($line =~ /^>/) {
            # End of input block, output and reset
            say $count;
            $count = 0;
        } else {
            $count += length($line);
        }
    }
    
    # Have reached the end of the input files
    say $count;