Alexx
Alexx

Reputation: 475

How to resolve this warning in Perl

I asked this type of ques previously but didn't provide the full code.

I am reading below file and checking the max word width present in each column and then write it to another file with proper alignment.

id0 id1 id2 batch
0   34  56  70
2   3647    58  72  566
4   39  616 75  98  78 78987 9876 7899 776
89  40  62  76
8   42  64  78
34  455 544 565

My code:

unlink "temp1.log";
use warnings;
use strict;
use feature 'say';
my $log1_file = "log1.log";
my $temp1 = "temp1.log";
open(IN1, "<$log1_file" ) or die "Could not open file $log1_file: $!";
my @col_lens;

while (my $line = <IN1>) {
    my @fs = split " ", $line;
    my @rows = @fs ;
    @col_lens =  map (length, @rows) if $.==1;
    for my $col_idx (0..$#rows) {
        my $col_len = length $rows[$col_idx];
        if ($col_lens[$col_idx] < $col_len) {
            $col_lens[$col_idx] = $col_len;
        }
    };
};
close IN1;
open(IN1, "<$log1_file" ) or die "Could not open file $log1_file: $!";
open(tempp1,"+>>$temp1") or die "Could not open file $temp1: $!";
while (my $line = <IN1>) {
    my @fs = split " ", $line;
    my @az;
    for my $h (0..$#fs) { 
        my $len = length $fs[$h]; 
        my $blk_len = $col_lens[$h]+1;
        my $right = $blk_len - $len;
        $az[$h] = (" ") . $fs[$h] . ( " " x $right );
    }
    say tempp1 (join "|",@az);
};

My warning

Use of uninitialized value in numeric lt (<) at new.pl line 25, <IN1> line 3.
Use of uninitialized value in numeric lt (<) at new.pl line 25, <IN1> line 4.
Use of uninitialized value in numeric lt (<) at new.pl line 25, <IN1> line 4.
Use of uninitialized value in numeric lt (<) at new.pl line 25, <IN1> line 4.
Use of uninitialized value in numeric lt (<) at new.pl line 25, <IN1> line 4.
Use of uninitialized value in numeric lt (<) at new.pl line 25, <IN1> line 4.

I am getting the output correctly but don't know how to remove this warnings.

Upvotes: 2

Views: 597

Answers (3)

ikegami
ikegami

Reputation: 386646

$col_idx can be up to the number of fields on a line, minus one. For the third line, this is more than the highest index of @col_lens, which contains at most 3 elements. So doing the following makes no sense:

if ($col_lens[$col_idx] < $col_len) {
   $col_lens[$col_idx] = $col_len;
}

Replace it with

if (!defined($col_lens[$col_idx]) || $col_lens[$col_idx] < $col_len) {
   $col_lens[$col_idx] = $col_len;
}

With this, there's really no point checking for $. == 1 anymore.

Upvotes: 5

vkk05
vkk05

Reputation: 3222

You're getting uninitialized warning because, while checking the $col_lens[$col_idx] < $col_len condition, one or both of them are undef.

Solution 1:

You can skip checking this condition by the use of next statement.

for my $col_idx (0..$#rows) {
        my $col_len = length $rows[$col_idx];
        
        next unless $col_lens[$col_idx];
        
        if ($col_lens[$col_idx] < $col_len) {
            $col_lens[$col_idx] = $col_len;
        }
    }

Solution 2: (Not advised):
You can simply ignore Use of uninitialized value.. warnings by putting this line at top of your script. This will disable uninitialized warnings in a block.

no warnings 'uninitialized';

For more info, please refer this link

Upvotes: 5

Polar Bear
Polar Bear

Reputation: 6818

Following code demonstrates one of many possible ways for solution to this task

  • read line by line
  • get length of each field
  • compare with stored earlier
  • adjust to max length
  • form $format string for print
  • print formatted data
use strict;
use warnings;
use feature 'say';

my(@data,@length,$format);

while ( <DATA> ) {
    my @e = split ' ';
    my @l = map{ length } @e;
    $length[$_] = ($length[$_] // 0) < $l[$_] ? $l[$_] : $length[$_] for 0..$#e;
    push @data,\@e;
}

$format = join '  ', map{ '%'.$_.'s' } @length;
$format .= "\n";

for my $row ( @data ) {
    printf $format, map { $row->[$_] // '' } 0..$#length;;
}

__DATA__
id0 id1 id2 batch
0   34  56  70
2   3647    58  72  566
4   39  616 75  98  78 78987 9876 7899 776
89  40  62  76
8   42  64  78
34  455 544 565

Output

id0   id1  id2  batch
  0    34   56     70
  2  3647   58     72  566
  4    39  616     75   98  78  78987  9876  7899  776
 89    40   62     76
  8    42   64     78
 34   455  544    565

Upvotes: 1

Related Questions