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

When I am running the below code , I am getting the following error :
Use of uninitialized value $_ in pattern match (m//) at main.pl line 10,
<STDIN> line 5 (#1)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.

#! /usr/bin/perl use strict; use warnings; use diagnostics; chomp( my @input = <STDIN> ); foreach my $line (@input){ if ( /fred/ ){ print "Matched : $line"; } }

But when I replace $line with $_ , the code is running absolutely fine , I know I am doing some conceptual error , kindly help me fix it

Replies are listed 'Best First'.
Re: Beginner in perl : Use of uninitialized value
by jwkrahn (Abbot) on Dec 28, 2018 at 05:49 UTC
    foreach my $line (@input){ if ( /fred/ ){

    Is the same as:

    foreach my $line (@input){ if ( $_ =~ /fred/ ){

    You need to change it to:

    foreach my $line (@input){ if ( $line =~ /fred/ ){

      Thanks @jwkrahn for clearing this.

Re: Beginner in perl : Use of uninitialized value
by kcott (Archbishop) on Dec 28, 2018 at 06:11 UTC

    G'day Perl_Programmer1992,

    Many of Perl's operations use $_ as a default value. You may have seen print and the for loop used that way:

    $ perl -MO=Deparse -e 'for (0..2) { print }' foreach $_ (0 .. 2) { print $_; } -e syntax OK

    [See B::Deparse if the code in that example is unfamiliar to you.]

    $_ is also the default variable for a "pattern match (m//)". These are equivalent:

    /fred/ $_ =~ /fred/ $_ =~ m/fred/

    Relating all of that to your code: by assigning the value of each foreach iteration to $line, you do not assign the value to $_ (either explicitly or implicitly by default); consequently, $_ is undefined when used as the default value in /fred/.

    By the way, in case you didn't know, for and foreach are synonymous.

    — Ken

      Thanks Ken for the explanation , this is actually a very important concept as I am still in the initial phase of learning perl.

Re: Beginner in perl : Use of uninitialized value
by jimpudar (Pilgrim) on Dec 28, 2018 at 18:45 UTC

    Just another tip: there is no need to read all of STDIN into an array; you can iterate over each line as it comes in.

    while ( my $line = <STDIN> ) { ... }

    The diamond operator <> will do some pretty fancy stuff for you by default. You can for example leave out the explicit STDIN:

    while ( my $line = <> ) { ... }

    What is really cool about this is that now in addition to working with STDIN you can also pass a list of filenames to your Perl program and it will do the right thing.

    See perlop - IO Operators for more details on the diamond operator.

    Of course you also don't need to set an explicit loop variable for a program of this size; you can just use $_:

    while (<>) { ... }

    And at this point, you may want to look into Perl's -n command line option, which will automatically wrap your entire program inside that exact same loop:

    bash:~$ perl -nE '...'

    πάντων χρημάτων μέτρον έστιν άνθρωπος.

      Just another tip: there is no need to read all of STDIN into an array; you can iterate over each line as it comes in.
      foreach my $line (<STDIN>) { ... }

      The problem with that is that the foreach loop will read all lines into a list in memory first.

      You need a while loop to iterate over one line at a time:

      while ( my $line = <STDIN> ) { ... }

        Quite right, that's what I get for posting without testing my code :).

        I edited my comment to correct this.

        πάντων χρημάτων μέτρον έστιν άνθρωπος.