【问题标题】:Perl diamond operator in double while loop hangs双while循环中的Perl菱形运算符挂起
【发布时间】:2018-11-18 16:19:56
【问题描述】:

在我的 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”,然后它挂起。

【问题讨论】:

  • 请向我们展示一些有代表性的输入数据和相应的日志输出。
  • @Corion 您可以使用任何文本文件作为输入。输出实际上正是我想要的。那不是问题。问题是 在最后一行之后挂起。只需使用任何文件运行脚本,您就会看到它会挂在“打印“获取行””处,表明 不会继续。
  • 嗯 - 我猜它只是按设计工作 - 你永远不会检查 eof() 并尝试从默认输入中再读取一行。如果您使用&lt;&gt;,一旦@ARGV 用尽,它将回退到从STDIN 读取。见perldoc.perl.org/functions/readline.html。我不明白你的逻辑是什么,但我想你在尝试阅读另一行之前想要一个last if eof;
  • @Corion 从文档中它说each call reads and returns the next line until end-of-file is reached, whereupon the subsequent call returns undef 所以我没想到它会退回到STDIN,但预计它会返回undef。这就是if (not($l)) {last;} 应该做的。检查该行是否为 undef 并退出 while 循环。
  • @Corion last if eof&lt;&gt; 之前会成功。但我仍然不明白为什么它不会只返回undef。是不是&lt;&gt; 会返回一次undef,但第二次会转到STDIN,因为这就是发生的情况。只有第二次挂了,第一次还是输出undef。

标签: perl while-loop diamond-operator


【解决方案1】:

欢迎使用 Perl。

您的代码的问题是您无法逃避外部循环。 &lt;&gt; 将在到达文件末尾时返回 undef。此时,您的内部循环结束,外部循环将其送回。强制进一步读取会导致 &lt;&gt; 开始查看从不发送 EOF 的 STDIN,因此您的循环将永远继续。

由于这是您的第一个 Perl 脚本,我将用一些 cmets 为您重写它。 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;

【讨论】:

    【解决方案2】:

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

    在我的代码中遇到相同的“问题”。

    从标准输入获取 EOF。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-26
      • 1970-01-01
      • 2010-10-18
      • 1970-01-01
      • 2012-01-24
      • 2014-06-06
      • 2022-01-04
      • 1970-01-01
      相关资源
      最近更新 更多