首页 > 解决方案 > 处理@ARGS 的两个警告

问题描述

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

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模块(使用这个数组)之前“剪切”一些数据。

如何解决?

标签: perl

解决方案


让我们稍微扩展一下这些评论。

想象@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);
}

我认为这更容易理解。


推荐阅读