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

Perl : Can anyone tell me how to resolve this warnings

提问人:Alexx 提问时间:10/29/2020 最后编辑:Alexx 更新时间:10/29/2020 访问量:113

问:

代码部分 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 

Perl 警告

评论

2赞 ikegami 10/29/2020
1a) 您在一个地方和另一个地方使用。1b) 你从第二个元素开始,然后走得太远@array@fieldsfor my $j (0..$#array)
2赞 ikegami 10/29/2020
2)应该是[0-9]*[0-9]+
1赞 ikegami 10/29/2020
如果您不希望收到有关数组中未定义元素的警告,请不要将 undef 放在数组中
5赞 ikegami 10/29/2020
请根据需要提供最小的、可运行的问题演示
1赞 TLP 10/29/2020
@HG 当你有 3 个答案时,你不应该改变问题的前提。这是您正在询问的新代码,它应该在一个新问题中。完成这个并写一个新的。

答:

3赞 Dave Cross 10/29/2020 #1

我认为交换到是一个错别字。@array@fields

在这里,您可以获得数组中的元素数:

my $length = @array;

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

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

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:每个数组都有一个与之关联的特殊变量 (),其中包含数组中最高的索引号。在本例中,这将是 4。$#arrayname

但我们可以改进这一点。你实际上并不想要数组索引,是吗?你真正想要的是数组元素。你可以直接得到这些。

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

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

for (@array) {   # stores each element in turn in $_
  if (/dat/) {   # checks regex against $_
    ...
  }
}
4赞 TLP 10/29/2020 #2

写下代码的分步演练。(感谢ikegami在评论中提到了其中的一些内容)

代码部分 1:

这部分的问题:

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

代码第 2 部分:

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

您进一步评论:

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

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

2赞 Polar Bear 10/29/2020 #3

让我们尝试稍微更改一下 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