Perl:谁能告诉我如何解决此警告

时间:2020-10-29 06:01:25

标签: perl warnings

代码第1部分:

      my $length = @array;

269   for (my $j=1; $j <= $length; $j+=1) {
270
271     if ( $fields[$j] =~ /dat/) {
    
         }}

警告1:

Use of uninitialized value within @array in pattern match (m//) at wrk.pl line 270

代码部分2:在这里,我试图将十进制转换为十六进制

70 while (my $line = <DATA>) {
71     $line =~ s/ '([0-9]*)' / sprintf '0x%x', $1/eg;
72     print OUT $line;
       }

警告2:

Argument "" isn't numeric in sprint at wrk.pl line 71

更新

在放置for (my $j=1; $j <= $#array; $j+=1)之后,以上两个警告均已解决,对于第二个警告,我更改了$line =~ s/ '([0-9]+)' / sprintf '0x%x', $1/eg;

我又收到两个警告

代码第3部分:在这里,我正在检查每列中存在的最大字宽

my @col_lns;
while (<file>) {
  my @row = split " ",$_;
  @col_lns = map ((length) @rows) if $. ==1;

for ( my $col_l =0; $col_l <$#row; $col_l+=1) {
my $col_ln = length $row[$col_l];

  if ($col_lns[$col_l] < $coln)    ###Here I am getting warning
{
  $col_lns[$col_l] = $coln;
}
}

警告3:

Use of uninitialized value in numeric lt (<) 

代码第4部分;

my $pack1 = substr($add,4,4);
my $pack2 = substr($add,0,4);

警告4

Use of $add in substr
substr outside of string 

3 个答案:

答案 0 :(得分:4)

逐步编写代码。 (向池上致谢,因为他们在评论中提到了其中的一些内容)

代码第1部分:

这部分有问题:

  • 您检查数组@array的长度,然后使用该长度遍历@fields数组。
  • 您从数组索引1开始,然后转到等于数组长度的数组索引(假设使用了正确的数组长度)。这是一次性错误。数组从0开始。您应该从0循环到数组$#fields的最大 index (小于长度1)。
  • 警告1与代码中写的不匹配。该错误应该与数组@fields有关,这是您在代码中使用的。
  • 警告1给出了错误的行号270。 (最后两点表明您在复制错误消息后已更改了代码,这是一件不好的事)
  • 警告1表示@array数组中的一个值未定义。由于循环条件中存在一次性错误,因此很好的猜测是,未定义的值位于数组的末尾,一旦修复了循环条件,该警告就会消失。

代码第2部分:

  • 您正在将空字符串""输入到sprintf,它会警告您。由于您的匹配用空格和单引号引起来,因此输入中很可能是空字符串(即'')。为避免与之匹配,可以使用+代替*,即[0-9]+。量词+表示“匹配1次或多次”,而*表示“匹配0次或多次”。请注意,这样做还会留下引号和空格,而引号和空格在其他时间会被删除。
  • DATA是文件内数据的保留文件句柄,使用文件底部的__DATA__标记。除非您正在执行此操作,否则应选择另一个文件句柄。最好是词法,例如my $fh

您进一步评论:

@ikegami,更改后仍会收到警告。

由于您没有提及这些警告,因此我们无法为您提供帮助。

答案 1 :(得分:3)

我认为将@array换成@fields是错字。

在这里,您将获得数组中元素的数量:

my $length = @array;

因此,如果您的数组包含五个元素,那么$length现在将包含5。数组中的五个元素的索引为0到4。

现在,您遍历数组的元素:

for (my $j=1; $j <= $length; $j+=1) {
  ...
}

很显然,我不知道您的数组中有什么,但是从索引1开始通常看起来很奇怪,通常从索引0开始。您的代码一直持续到索引5,但是您的数组没有索引5。如上所述,您的索引从0到4。

因此,您尝试访问索引5处的元素,没有此类元素,并且在尝试使用该值时会收到“未定义的值”警告。

所以您的代码应该看起来像这样:

# Start at 0; continue only while $j is less than $length
for (my $j=0; $j < $length; $j+=1) {
  ...
}

但是,这不是编写此代码的“ Perlish”方法。 Perl程序员很少使用这种“ C样式”循环语法。我们喜欢遍历值列表。

for my $j (0 .. $#array) {
  ..
}

这与您的原始代码完全等效,但是(据我认为)它更容易阅读。

  • ..:这是“范围运算符”。它返回0到$#array之间的整数列表
  • $#array:每个数组都有一个与之关联的特殊变量($#arrayname),该变量包含数组中的最高索引号。在这种情况下,该值为4。

但是我们可以对此进行改进。您实际上并不需要数组索引,是吗?您真正想要的是数组元素。您可以直接获得它们。

for my $element (@array) {
  if ($element =~ /dat/) {
    ..
  }
}

最后,Perl程序员可能会在此处使用$_作为变量,因为您通常不需要实际编写它:

for (@array) {   # stores each element in turn in $_
  if (/dat/) {   # checks regex against $_
    ...
  }
}

答案 2 :(得分:2)

让我们尝试稍微更改OP的代码以使可行的代码示例成为可能。

注1:OP没有提供输入数据示例

注意:#2:s/ '([0-9]+)' /sprintf ' 0x%x ', $1/eg;会更正确

use strict;
use warnings;
use feature 'say';

my @array = ( 'First sentence here', undef, 'Second dat sentence', undef, 'One more data sentence');

say '---- Part 1 ----';

for ( @array ) {
    if( defined $_ and /dat/ ) {
        say;
    }
}

say '---- Part 2 ----';

while ( <DATA> ) {
    s/ '([0-9]*)' /sprintf ' 0x%x ', $1/eg;
    print $_;
}

__DATA__
some test data placed here for a test
ok, lets put some digits '3824' bits
some more '8902' bytes some text
number of files '0x834' you did not account for this
now finish with '123456' number

输出

---- Part 1 ----
Second dat sentence
One more data sentence
---- Part 2 ----
some test data placed here for a test
ok, lets put some digits 0xef0 bits
some more 0x22c6 bytes some text
number of files '0x834' you did not account for this
now finish with 0x1e240 number