little_mistress has asked for the wisdom of the Perl Monks concerning the following question:
here is a small and simple script, and yet its doing something that i dont understand
On line ten, its giving a "Use of uninitialized value at test.pl line 10." warning.
It seems like all the values are indeed initialized. What am I missing?
#!C:\Perl\bin\perl.exe -w
$file = 'foo.txt';
open(SESAME, $file);
@lines = <SESAME>;
close(SESAME);
$total = @lines;
for ($i=0; $i <= $total; $i++)
{
if ($lines[$i] eq "\n") # This is line the line
{
pop @lines;
$i = $i -1;
$total = @lines;
}
}
print "There are $total records in $file\n";
Use of uninitialized value at test.pl line 10.
Re: I don't understand why I'm getting an unitialized value warning
by btrott (Parson) on Apr 12, 2000 at 23:28 UTC
|
my @lines = qw/a b c d e/;
my $total = @lines;
$total is now 5, but the last array index is 4, because
the indices start at 0. In your for loop, $i goes from
0 to 5, and when $i is 5, you're trying to access
$lines[5]
which doesn't exist.
The solution, of course, is to change your for loop:
for my $i (0..$total-1) {
...
Of course, if this is all you're doing, you may as well just
use grep:
my $total = grep $_ ne "\n", @lines;
| [reply] [d/l] [select] |
|
god im such a duhhhh ....
ok ok thanks
This was sent to me by a coworker so i dont know if it's real code
or just and example to show me whats going on. But, no i didn't write it
and i don't know what its for or if its anything more than an example.
| [reply] |
Re: I don't understand why I'm getting an unitialized value warning
by chromatic (Archbishop) on Apr 12, 2000 at 23:48 UTC
|
I'm a little confused as to the purpose of this snippet. Are records in your file separated by an extra newline? I ask because it *appears* that your code tests each line in @lines to see if it only contains "\n". If so, it pops the last line off of the array (probably not what you want), decreases the number of lines expected (probably what you want) and decrements the loop index (which will cause the loop to hit the newline again, and keep popping off good lines from your array, probably the source of your error message).
If you want to get rid of blank lines more easily, one idea is:
#!C:\Perl\bin\perl.exe -w
use strict; # I'm a masochist
my $file = shift || 'foo.txt'; # why not
my @lines;
open(SESAME, $file) || die "Cannot open $file: $!"; # save debuggin
+g time
while (<SESAME>) {
chomp;
next unless $_;
push @lines, $_;
}
close(SESAME) || die "Cannot close $file: $!";
my $total = @lines;
print "There are $total records in $file\n";
Not too bad. I can make it shorter, though:
{
local *SESAME; # localizing a filehandle saves debugging ti
+me too
open (SESAME, $file) || die "Foo: $!";
local $/ = "\n\n"; # "line" delimiter is now two newlines
@lines = <SESAME>;
close (SESAME) || die "Bar: $!";
}
Bingo! One record per line in the array. You could also throw a split in there on newlines if you wanted records stored in the array one line at a time. | [reply] [d/l] [select] |
Re: I don't understand why I'm getting an unitialized value warning
by plaid (Chaplain) on Apr 13, 2000 at 01:21 UTC
|
Here I'm assuming chromatic's assessment of the code is
correct (that \n\n is the record delimiter). This isn't
particularly useful, but I like ugly one-liners:)
perl -an0777 -F"\n\n" -e 'END { print "There are ", scalar @F, " recor
+ds in $ARGV\n" }' foo.txt
| [reply] [d/l] |
Re: I don't understand why I'm getting an unitialized value warning
by Doc Technical (Initiate) on Apr 13, 2000 at 10:36 UTC
|
Here's how I'd make sure there are no blank records in the file,
to get an accurate count of the records that have data in them:
(I've been doing a lot with regular expressions and file parsing lately)
local $/; # Perl's record separator - default is \n unless...
$/ = undef; # ... we make it undefined!
open(SESAME,$file); # open the file
$f = (<SESAME>); # the entire file, including all \n chars, is now sitting in a single scalar!
close(SESAME);
$f = s/\n+/\n/gs; # regular expression replaces contiguous strings of \n chars with single \n chars.
$f = s/^\n//s; # regex removes \n at the start of the string, if there is one.
$f = s/\n$//s; # regex removes \n at the end of the string, if there is one.
@x = split(/\n/,$f); # split string on the \n char, store split values in array @x
$x = @x; # the number of elements in @x
print "There are $x records in file $file\n";
exit(0);
| [reply] |
|
Sorry about the repetition. new here and getting the hang of the way response submissions must be formatted. The last one is correct.
BTW, it would sure be nice if the folks who run this put up a "your response has been submitted" screen when a submission is made, instead of re-displaying the submission request page again.
| [reply] |
Re: I don't understand why I'm getting an unitialized value warning
by Doc Technical (Initiate) on Apr 13, 2000 at 10:20 UTC
|
Here's how I'd make sure there are no blank records in the file,
to get an accurate count of the records that have data in them:
(I've been doing a lot with regular expressions and file parsing lately)
local $/; # Perl's record separator - default is \n unless...
$/ = undef; # ... we make it undefined!
open(SESAME,$file) # open the file
$f = (<SESAME>); # the entire file, including all \n chars, is now sitting in a single scalar!
close(SESAME);
$f = s/\n+/\n/gs; # regular expression replaces contiguous strings of \n chars with single \n chars.
$f = s/^\n//s; # removes \n at the start of the string, if there is one.
$f = s/\n$//s; # removes \n at the end of the string, if there is one.
@x = split(/\n/, $f); # split string on the \n char, store split values in array @x
$x = @x; # the number of elements in @x
print "There are $x records in file $file\n";
exit(0);
| [reply] |
|
|