使用@ARGS的两个警告进行处理

时间:2019-01-14 19:20:56

标签: perl

小型调试问题,由于某些原因我无法解决。考虑以下代码:

use warnings;
my $flag = 0;
foreach my $i (0..scalar(@ARGV)) {
    $data{$OPTION} .= $ARGV[$i]." " if($flag);
    $flag = 1 if($ARGV[$i] =~ /$OPTION/);
    undef $ARGV[$i] if($flag);
}

我收到以下两个警告:

Use of uninitialized value within @ARGV in concatenation (.) or string at line 4
Use of uninitialized value in pattern match (m//) at line 5

我得到的原因是,我未定义@ARGV的某个值,然后它试图对其进行检查。

我这样做的原因是因为我想在使用@ARGV模块(使用此数组)之前先“剪切” GetOpt的某些数据。

如何解决?

1 个答案:

答案 0 :(得分:3)

让我们对这些评论进行一些扩展。

想象@ARGV包含四个元素。它们将具有索引0、1、2和3(因为Perl中的数组从零开始)。

您的循环如下所示:

foreach my $i (0..scalar(@ARGV)) {

您想访问@ARGV中的每个元素,因此您使用范围运算符(..)生成所有这些索引的列表。但是scalar @ARGV返回@ARGV中的元素数,即4。所以您的范围是0 .. 4.而且$ARGV[4]处没有值-因此您会收到“未定义值”警告(当您尝试读取数组末尾时)。

一种更好的方法是使用$#ARGV而不是scalar @ARGV。对于Perl中的每个数组变量(例如@foo),您还将获得一个变量(称为$#foo),该变量包含数组中的最后一个索引号。在我们的例子中,它是3,并且您的范围(0 .. $#ARGV)现在包含整数0 .. 3,并且您不再尝试读取数组末尾的内容,并且不会收到“未定义值”警告。

我建议还有其他改进。在循环内部,您仅使用$i来访问@ARGV中的元素。它仅在$ARGV[$i]之类的表达式中使用。在这种情况下,最好跳过中间人并遍历数组中的元素而不是索引。

我的意思是您可以这样编写代码:

foreach my $arg (@ARGV) {
    $data{$OPTION} .= $arg . " " if($flag);
    $flag = 1 if($arg =~ /$OPTION/);
    undef $arg if($flag);
}

我认为这更容易理解。