Perl: Alguém pode me dizer como resolver esses avisos

Oct 29 2020

Parte 1 do código:

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

Aviso 1:

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

Parte do código 2: Estou tentando converter o decimal em hexadecimal

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

Aviso 2:

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

Atualizar

Os dois avisos acima agora foram resolvidos após eu colocar e para o segundo aviso eu alterar .for (my $j=1; $j <= $#array; $j+=1)$line =~ s/ '([0-9]+)' / sprintf '0x%x', $1/eg;

Estou recebendo mais dois avisos

Parte do código 3 : Aqui estou verificando a largura máxima da palavra presente em cada coluna

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;
}
}

Aviso 3:

Use of uninitialized value in numeric lt (<) 

Código parte 4 ;

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

Aviso 4

Use of $add in substr
substr outside of string 

Respostas

4 TLP Oct 29 2020 at 16:05

Escrevendo passo a passo o passo a passo do código. (Crédito a ikegami por mencionar algo disso nos comentários)

Parte 1 do código:

Coisas erradas com esta parte:

  • Você verifica o comprimento do array e @array, em seguida, usa esse comprimento para percorrer o @fieldsarray.
  • Você começa no índice de array 1 e vai para o índice de array igual ao comprimento do array (assumindo que o comprimento correto do array foi usado). Este é um erro único. As matrizes começam em 0. Você deve fazer um loop de 0 ao índice máximo da matriz $#fields(um a menos que o comprimento).
  • Aviso 1 não corresponde ao que está escrito no código. O erro deve ser sobre array @fields, que é o que você usa no código.
  • O Aviso 1 fornece o número de linha incorreto 270. (Esses dois últimos pontos indicam que você alterou o código após copiar a mensagem de erro, o que é uma atitude inadequada)
  • Aviso 1 significa que um valor na @arraymatriz é indefinido. Como você tem um erro único nas condições do loop, um bom palpite é que o valor indefinido está no final da matriz e que esse aviso desaparece assim que você corrige a condição do loop.

Parte do código 2:

  • Você está alimentando o string vazio ""para sprintf, e ele o avisa sobre isso. Uma vez que sua correspondência está cercada por espaço e aspas simples, é provável que seja uma string vazia na entrada (ou seja ''). Para evitar a correspondência, você pode usar em +vez de *, ie [0-9]+. O quantificador +significa "corresponder 1 ou mais vezes", enquanto *significa "corresponder 0 ou mais vezes". Esteja ciente de que isso também deixará aspas e espaços, que são removidos em outras ocasiões.
  • DATAé um identificador de arquivo reservado para dados no arquivo, usando o __DATA__marcador na parte inferior do arquivo. A menos que seja isso que você está fazendo, você deve escolher outro identificador de arquivo. De preferência um léxico, por exemplo my $fh.

Você comenta mais:

@ikegami, ainda recebendo avisos após as mudanças.

Já que você não mencionou quais são esses avisos, não podemos ajudá-lo.

3 DaveCross Oct 29 2020 at 16:03

Presumo que trocar @arraypara @fieldsé um erro de digitação.

Aqui, você obtém o número de elementos em sua matriz:

my $length = @array;

Portanto, se sua matriz contém cinco elementos, $lengthagora conterá 5. Os cinco elementos em sua matriz terão os índices de 0 a 4.

Agora você percorre os elementos de sua matriz:

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

Obviamente, não sei o que está em seu array, mas parece estranho que você esteja começando no índice 1 - normalmente, você começaria no índice 0. E seu código continua até o índice 5 - mas seu array não tem um índice 5. Como eu disse acima, seus índices vão de 0 a 4.

Então, você tenta acessar o elemento no índice 5, não existe tal elemento e você obtém um aviso de "valor indefinido" quando tenta usar esse valor.

Portanto, seu código provavelmente deve ser assim:

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

No entanto, essa não é uma maneira muito "pervertida" de escrever esse código. Os programadores Perl raramente usam esta sintaxe de loop "estilo C". Gostamos de iterar em uma lista de valores.

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

Isso é exatamente equivalente ao seu código original, mas (na minha opinião) é muito mais fácil de ler.

  • ..: Este é o "operador de alcance". Ele retorna uma lista de inteiros entre 0 e$#array
  • $#array: Cada array possui uma variável especial ( $#arrayname) associada a ela que contém o número de índice mais alto do array. Nesse caso, será 4.

Mas podemos melhorar isso. Você realmente não quer os índices de array, quer? O que você realmente quer são os elementos do array . E você pode obtê-los diretamente.

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

Finalmente, um programador Perl provavelmente usaria $_como a variável aqui, já que você geralmente não precisa realmente escrevê-la:

for (@array) {   # stores each element in turn in $_ if (/dat/) { # checks regex against $_
    ...
  }
}
2 PolarBear Oct 29 2020 at 16:33

Vamos tentar mudar um pouco o código do OP para fazer um exemplo de código viável.

Nota # 1: nenhuma amostra de dados de entrada fornecida pelo OP

Nota: # 2: s/ '([0-9]+)' /sprintf ' 0x%x ', $1/eg;seria mais correto

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

Resultado

---- 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