chiru has asked for the wisdom of the Perl Monks concerning the following question:

Hi!, I'm trying to create a script which will ask user for file and checks if it has at least 5 line, if it does than print first and last line. I'm getting following errors Use of uninitialized value $lines in concatenation (.) or string at c:\test\perl\test.pl line 9, <FILE> line 6. Use of uninitialized value $lines in numeric lt (<) at c:\test\perl\test.pl line 14. I will really appreciate your help. You may enlight me if there is different way to do it. Thanks, chiru

use warnings; use strict; print "please enter name of file: "; chomp($ARGV=<>); open (FILE, $ARGV) or die "Can't open '$ARGV': $!"; my $lines++ while(<FILE>); print "\$lines: $lines"; my $last; my $first = <FILE>; while (<FILE>) { $last = $_ } close FILE; if($lines<5){ print "file must have more than 5 lines"; } else{ print "\$first: $first"; print "\$last: $last"; }
  • Comment on getting error "Use of uninitialized value $lines in concatenation (.) or string at line 6
  • Download Code

Replies are listed 'Best First'.
Re: getting error "Use of uninitialized value $lines in concatenation (.) or string at line 6"
by Athanasius (Archbishop) on Jul 03, 2014 at 02:54 UTC

    Hello chiru, and welcome to the Monastery!

    There are two major problems in your script:

    1. my $lines++ while(<FILE>);

      This re-declares $lines on every iteration of the while loop. You need to declare it once only, before the loop:

      my $lines; $lines++ while <FILE>;
    2. my $first = <FILE>;

      At this point, the filehandle FILE points to the end of the file, because this is the position it reached at the conclusion of the previous while loop. Call seek to reset it:

      seek FILE, 0, 0; my $first = <FILE>;

    Note also that $ARGV has a special meaning in Perl (see perlvar#Variables-related-to-filehandles). You should use an ordinary lexical variable instead: chomp(my $file = <>);

    And of course the design of this script is inefficient, since it reads the file twice. See NetWallah’s answer for a better, one-pass, approach.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      It works now. Thanks a lot for explanation and pointing out my mistake. I really appreciate it.

Re: getting error "Use of uninitialized value $lines in concatenation (.) or string at line 6
by NetWallah (Canon) on Jul 03, 2014 at 01:13 UTC
    too many errors in your code - here is a one-line alternative that takes the file name on the command line:
    perl -ne "$first ||=$_; $last=$_; $count++}{die qq(ERROR found $count +lines. Need >5) unless $count>5; print qq(FIRST:$first\nLAST:$last\n) +" YOUR-FILE-NAME-here.txt
    Change to single quotes for Linux.

            What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?
                  -Larry Wall, 1992

      Thanks for your reply. I'm still trying to figure out your code. Why did you use }{ between $count++ and die? When i tried to run this code, I got following error message:
      syntax error at -e line 1, near "||="
      syntax error at -e line 1, near "unless >"

        Why did you use }{ between $count++ and die?

        The -n switch to perl wraps the entire script in a loop, as follows:

        LINE: while (<>) { ... # your program goes here }

        So the provided code deparses to this:

        LINE: while (defined($_ = <ARGV>)) { $first ||= $_; $last = $_; ++$count; } { die "ERROR found $count lines. Need >5" unless $count > 5; print "FIRST:$first\nLAST:$last\n"; }

        Note how the "butterfly operator" (that's }{) is used to add some extra bit of code that'll be run after the loop that -n adds finishes.

        When i tried to run this code, I got following error message: syntax error at -e line 1, near "||=" syntax error at -e line 1, near "unless >"

        As my brother said above: "Change to single quotes for Linux", i.e.:

        perl -ne '$first ||=$_; $last=$_; $count++}{die qq(ERROR found $count +lines. Need >5) unless $count>5; print qq(FIRST:$first\nLAST:$last\n) +' YOUR-FILE-NAME-here.txt

        This is to keep your shell from messing with the script by interpreting special characters.

Re: getting error "Use of uninitialized value $lines in concatenation (.) or string at line 6
by gurpreetsingh13 (Scribe) on Jul 03, 2014 at 04:18 UTC
    As suggested above, here is a slightly modified version of your script with addition of just 2 lines.
    use warnings; use strict; print "please enter name of file: "; chomp($ARGV=<>); open (FILE, $ARGV) or die "Can't open '$ARGV': $!"; my $lines; $lines++ while(<FILE>); print "\$lines: $lines"; my $last; seek FILE,0,0; my $first = <FILE>; while (<FILE>) { $last = $_ } close FILE; if($lines<5){ print "file must have more than 5 lines"; } else{ print "\$first: $first"; print "\$last: $last"; }

      Thanks for your effort. I will use $file instead of $ARGV like Athanasius suggested.