I am testing perl script using this example found on the forum. I took the sample data and put it in a separate file and using an open to try it this way.
I don't understand why I would be getting undef. I am getting the msg:
Use of uninitialized value in join or string at ./h.pl line 15, line 4.
#!/usr/local/bin/perl
use warnings;
use strict;
use Data::Dumper;
use Text::CSV_XS;
open my $fh, '<', 't.out' or die "Unable to open: $!";
my $csv = Text::CSV_XS->new( { sep_char => "\t" } );
my @list;
$csv->column_names ($csv->getline ($fh));
while ( my $hr = $csv->getline_hr($fh) ) {
push @list, $hr->{'Ball'};
开发者_StackOverflow}
print "@list\n";
print Dumper(\@list);
Test file (t.out)
Camera Make Camera Model Text Ball Swing
a b c d e
f g h i j
k l m n o
$ od -cx t.out
0000000 C a m e r a M a k e \t C a m e
6143 656d 6172 4d20 6b61 0965 6143 656d
0000020 r a M o d e l \t T e x t \t B a
6172 4d20 646f 6c65 5409 7865 0974 6142
0000040 l l \t S w i n g \n a \t b \t c \t d
6c6c 5309 6977 676e 610a 6209 6309 6409
0000060 \t e \n f \t g \t h \t i \t j \n k \t l
6509 660a 6709 6809 6909 6a09 6b0a 6c09
0000100 \t m \t n \t o \n \0
6d09 6e09 6f09 000a
0000107
Results:
$VAR1 = [
undef,
undef,
undef
];
If $csv->getline_hr($fh)
returns an undefined value, you will get the warning "Use of uninitialized value in join or string at ...
" if you try to print the list @list
.
You can test this explicitly with a simple program:
use strict;
use warnings;
my @list;
my $x = undef; # This is similar to what may happen in your program on the `push @list, @hr->{'Name'}` line
push @list, $x;
print "@list\n";
Also, you may want to use Data::Dumper
and then print Dumper(\@list)
instead if you are just doing debugging, since you won't get any warnings, and you will get a clearer picture of what is stored in your data structure.
In the question you refer to, I also wrote this on the last line:
ETA: If you're going to cut & paste to try it out, make sure that the tabs are carried over in the data.
Did you make sure that your tabs survived the copy/paste into your file 't.out'
?
This module is rather unforgiving about bad formats in the data file.
Update:
Be aware that a field such as 'Ball '
will be considered different than 'Ball'
. I.e. if you have additional whitespace, it will screw things up.
What you may try out to correct that is adding allow_whitespace => 1,
to the options of the $csv
object. This will correct any subtle whitespace errors in your input file.
You can also check for format errors by printing the header keys with
print Dumper $csv->column_names();
As others have mentioned, it is very possible that @list
never got a value in it. If $csv->getline_hr($fh)
returns an undef the first time through, you'll never push anything into @list
.
There are two things you can do:
- You can test if
@list
is uninitialized before printing it - You can loosen the
use warnings
pragma not to include uninitialized warnings:
Here's how you can do your testing:
if (@list) {
print "List = " . @list . "\n";
}
else {
print "List has no values\n";
}
You can use scalar @list
as Igor Zinov'yev shows, but that's not really necessary in this case and I think the simple if (@list)
is clearer. You can also use if (defined @list)
which is very clear, but has been discouraged over the last few years.
If this is a temporary thing (just seeing if your code works or not), you can loosen the use of strict:
no warnings qw(uninitialized);
print "@list\n"; #Now you won't get a warning if @list has no value
use warnings; #Turn the warnings back on. It helps you code better
A slight Word 'o Warning: In this case, your statement won't print anything and that might confuse you even more. Always put a prompt of some sort to make sure something prints:
print "\@list = @list\n";
I prefer this as a temporary solution when I'm printing out a lot of debugging statements which I'll later remove. In fact, I'll create a special debug
subroutine for these types of messages:
use strict;
use warnings;
use constant DEBUG_LEVEL => 1; #0 = no debug messages 1 = debug messages
[...]
while (yadda, yadda, yadda) {
push @list, $hr->{Name};
}
debug (qq(\@list = ") . join "|", @list . qq("));
[...]
sub debug {
my $message = shift;
return if (not DEBUG_LEVEL);
no warnings qw(uninitialized);
print qq(DEBUG: $message\n);
use warnings; #Not really needed since the code block ends
return $message;
}
It seems like your @list
array is undefined. Try checking it:
if (scalar @list) {
print "@list\n";
}
If your while loop has never been executed, scalar @list
will return 0
, because the array is empty.
精彩评论