【问题标题】:Why am I getting an uninitialized value warning when reading two lines at a time?为什么一次读取两行时会收到未初始化值警告?
【发布时间】:2015-10-12 18:52:29
【问题描述】:

我正在尝试使用 while 循环一次读取两行,但出现此错误:

line    1
line    2
line    3
Use of uninitialized value in concatenation (.) or string at ....
Use of uninitialized value in concatenation (.) or string at ....
Use of uninitialized value in concatenation (.) or string at ....

脚本:

#!/usr/bin/perl 
use warnings;
use strict;

my $count = 1;
while ( my $two_lines = <DATA> . <DATA> ) {
    print $two_lines;
}


__DATA__
line    1
line    2
line    3

【问题讨论】:

  • perl v5.20,也许这就是原因。有没有办法解决这个错误?
  • 输出很好,但是给出了这个错误信息。
  • 只要连接返回“某事真实”,您就不会读取到文件末尾,而是循环。您的问题的核心是您正在尝试阅读(并用于连接)第 4、5 和 6 行。

标签: perl filehandle


【解决方案1】:

readline 运算符&lt;HANDLE&gt; 在读取耗尽的文件句柄(在标量句柄中)时返回 undef。因此,当您从DATA 读取(缺失的)第 4 行时,第一个警告出现在 while 循环的第二次迭代中。 接下来的两个警告来自第 3 次迭代,当您在耗尽的文件句柄上调用 &lt;DATA&gt; 两次时。

您可以通过使用不是undef 的表达式来解决此问题。由于您使用的是 perl >=v5.16,因此您可以使用

while (my $line = (<DATA> // '') . (<DATA> // '')) { ...

【讨论】:

  • 我在两个版本上都尝试了相同的代码。实际上,错误出现在 v5.21 中(@toolic 在评论中也提到过)而不是 v5.16。这帮助我修复了 v5.21 中的警告,但我无法理解代码中发生了什么。你能再解释一下吗?
  • 当您的程序中__DATA__ 标记后面有三行文本并且您调用&lt;DATA&gt; 六次时会发生什么?前 3 次返回三行文本,后 3 次返回 undef。当您执行大多数二元运算并且其中一个操作数是 undef 并启用警告时,您会收到 Use of uninitialized value ... 警告消息。
  • 如果最后一行只包含0(无分隔符)并且是奇数行,这将无法工作。
【解决方案2】:

这并不是真正的错误,它只是一个警告。您应该在偶数行号文件上收到 2 个警告,在奇数行号文件上收到 3 个警告。当它第一次通过while表达式时,它从第一次读取罚款,然后当它第二次读取时,文件句柄为空,并打印警告。因为它第一次返回了一些东西,所以它会执行while循环的内容。最后一次,它将评估文件流两次,一无所获并中止循环,但两次都警告它试图连接空读取。如果你需要一个while循环,我会这样做

while ( my $first_lines = <DATA> ) {
    if (my $second_line = <DATA> ){
         print $first_lines . $second_line;
    }else{
        print $first_lines
        break;
    }
}

【讨论】:

  • 不,这确实是一个错误。警告可以像异常一样指示错误。
【解决方案3】:

readline aka &lt;$fh&gt; 返回 undef 表示文件结束(或错误)。你不是在检查那个。修复:

while (1) {
   defined( my $line1 = <DATA> )
      or last;
   defined( my $line2 = <DATA> )
      or die("Premature end of file\n");

   print($line1 . $line2);
}

【讨论】:

  • 没用,这里是错误:Value of &lt;HANDLE&gt; construct can be "0"; test with defined()
  • 哼,不知道他们添加了那个警告。我添加了一个解决方法,尽管它并不是真正需要的。
【解决方案4】:

你可能不知道的是

while ( my $line = <DATA> ){ ... }

简称

while ( defined( my $line = <DATA> ) ){ ... }

这种转换只发生在这样的简单结构上。

如果它没有检查definedness,那么如果它只包含0,它可以跳过最后一行。
(其他行也保证有行分隔符,因此它们将继续正常工作。)


一种使其一次或两行类似地工作的方法是:

# take advantage of the built-in transformation
while ( my $two_lines = <DATA> ) {
  $two_lines .= <DATA> // '';

  ... # your code here
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    • 2011-01-16
    • 2012-01-31
    • 1970-01-01
    • 2016-03-03
    • 2018-11-24
    • 2019-11-04
    相关资源
    最近更新 更多