双 while 循环中的 Perl 菱形运算符挂起

Perl diamond operator in double while loop hangs

在我的 Perl 脚本中,我有一个双重无限 while 循环。我用钻石运算符从文件中读取行。但不知何故,如果我的脚本到达文件的最后一行,它不会 return 取消定义,而是永远挂起。

如果我将代码缩减为单个 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" 然后挂起。

欢迎使用 Perl。

您的代码存在的问题是您无法逃离外循环。 <> 到达文件末尾时将 return 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 
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;

试试“echo | perl script.pl file.fa”。

适用于我的代码中存在相同“问题”的我。

从标准输入获取 EOF。