in reply to Split pattern doesn't match last line of file

I frequently use

next if $line =~ m/^\s+$/;
to skip lines that contain only white space. If you add a similar check (using $_ instead of $line, of course) to your while loop before the split statement it should solve the problem.

Update: Depending on how variable the input data is, you could also add a check to ensure that @cellen contains the expected number of elements and that they are defined before you try to access them.

Replies are listed 'Best First'.
Re^2: Split pattern doesn't match last line of file
by Util (Priest) on Jan 02, 2007 at 06:12 UTC

    ++bobf; I often used that line, but recently changed to using this form of it:

    next if not /\S/; # Skip blank lines
    I found that it was too easy to leave out (via typo) the ^,+, or $ in m/^\s+$/, and too hard to verify by eye.

    With my brain under the influence of Perl Best Practices, I see some possible bugs, and opportunities for improvements.

    • %saldi is not getting cleared between files! Is this what you want?
    • Magic <> is nice, but when you need eof() processing over multiple files, consider changing to do your own opens/closes, etc.
    • Sort your hash keys, or your output order may vary between runs.
    • Your totals will not line up when printed; consider printf() to format the output.
    • The code will be clearer if you name your fields instead of treating them as numbers, especially since the numbers change! (fields 3,4 become 0,1)
    • You are not chomping your input, so your last field contains newlines. It has not caused problems because the last field is only handled numerically.
    Working, tested example code:
    use strict; use warnings; foreach my $filename (@ARGV) { open my $fh, '<', $filename or warn "Can't open $filename: $!" and next; my %saldi; while ( <$fh> ) { chomp; next if not /\S/; # Skip blank lines my @fields = split /,/; if ( @fields != 5 ) { warn "Bad number of fields in file '$filename' line $."; next; } my ( $department, $currency, $year, $type, $amount ) = @fields +; $saldi{ $type } += $amount; } my ($basename) = ( $filename =~ m/^(\S+)\.txt/ ) or warn; print "$basename\n"; foreach my $type ( sort keys %saldi ) { my $total_amount = $saldi{$type}; printf "\t%-7s\t%7.2f\n", $type, $total_amount; } close $fh or warn "Can't close $filename: $!"; }

Re^2: Split pattern doesn't match last line of file
by GertMT (Hermit) on Jan 02, 2007 at 05:30 UTC
    guess it's a bit to advanced for me as I can't get it working though I understand the solution. Could you elaborate a bit more on where to put the
    next if $line =~ m/^\s+$/; and the $_?

      Sure - sorry for being too cryptic. Sometimes it's hard to tell how much detail is needed. :-)

      Insert a new line as follows (code snippet taken from your OP):

      while (<>) { next if m/^\s+$/; # <-- add this line my @cellen = ( split /,/, )[ 3, 4 ];

      The regex is anchored to the start (^) and end ($) of the string, and the pattern consists of one or more white space characters (\s+). See perlre and Pattern Matching, Regular Expressions, and Parsing (in the Tutorials section) for more information.

      Incidently, the code I added is a bit shorter than it could be, since it utilizes $_. A more verbose version could be:

      next if $_ =~ m/^\s+$/;
      or, if you wanted to explicitly assign the input text to a variable before processing, you could do something like this:
      while ( my $line = <>) { next if $line =~ m/^\s+$/; # <-- add this line my @cellen = ( split( /,/, $line ) )[ 3, 4 ];

      HTH