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

I'm working through some optional exercises from a recent Perl class. I'm stumped by this one: This code works fine:

my(@input_array) =(); chomp(@input_array = <STDIN>); #===== Search for a e i o and u (case insensitive) foreach $_ (@input_array) { if ($_ =~ /a/i && /e/i && /i/i && /o/i && /u/i) { print $_, "\n"; } }

This code fails with "Use of uninitialized value in pattern match (m//) at ./match4 line 19, <STDIN> line 3.":

my(@input_array) =(); my($one_line) = ''; chomp(@input_array = <STDIN>); #===== Search for a e i o and u (case insensitive) foreach $one_line(@input_array) { if ($one_line =~ /a/i && /e/i && /i/i && /o/i && /u/i) { print $one_line, "\n"; } }
What gives? Isn't it just about the same exact code?

For some reason, I keep getting these "uninitialized value" warnings on my OSX machine when running examples that gave me no errors on the Unix machine we used for my class. Something is different between the two Unix implementations, but I'm not sure what I'm doing wrong.

Thanks!

Charles Thomas
Madison, WI

Replies are listed 'Best First'.
•Re: $_ works, $my_variable doesn't?
by merlyn (Sage) on Mar 29, 2004 at 22:15 UTC
    $ perl -MO=Deparse,-p -e '$one_line =~ /a/i && /e/i && /i/i && /o/i && + /u/i' ((((($one_line =~ /a/i) and /e/i) and /i/i) and /o/i) and /u/i); ...
    Note that the later regexen aren't applying to $one_line, but rather $_. Oops!

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Randal,

      Very unintentionally cool to get this answer given that the problem in question is on page 91 of YOUR BOOK! Is saying "thanks" considered bad form around here? Don't want to anger anyone by posting follow-ups of "Thanks!".

      Consider my day made.

      Charles Thomas
      Madison, WI
Re: $_ works, $my_variable doesn't?
by eric256 (Parson) on Mar 29, 2004 at 22:19 UTC

    When you do a regex without the $var =~ in front it assumes $_ =~ /

    Here is a little script that goes threw it some. Mostly for my own experimentation but i figured i would share.

    $_ = "hello"; print "Hello\n" if /^h/ && /o$/; print "Hello agian\n" if $_ =~ /^h/ && /o$/; print "Hello a third time\n" if $_ =~ /^h/ && $_ =~ /o$/; $_ = "aeiou"; print "it has all the vowels\n" if (/a/i && /e/i && /i/i && /o/i && /u +/i); print "it still has all the vowels\n" if ($_ =~ /a/i && $_ =~ /e/i && +$_ =~ /i/i && $_ =~ /o/i && $_ =~ /u/i);

    Notice the progression and how all those different regex uses are realy the same. You should then see how yours fits in to the problem.


    ___________
    Eric Hodges
Re: $_ works, $my_variable doesn't?
by revdiablo (Prior) on Mar 29, 2004 at 22:20 UTC

    You seem to be misunderstanding how && works in this case. When you say:

        $_ =~ /a/i && /e/i && /i/i && /o/i && /u/i

    that essentially gets extrapolated to:

        ($_ =~ /a/i) && ($_ =~ /e/i) && ($_ =~ /i/i) && ($_ =~ /o/i) && ($_ =~ /u/i)

    Then when you write:

        $one_line =~ /a/i && /e/i && /i/i && /o/i && /u/i

    it similarly gets extrapolated to:

        ($one_line =~ /a/i) && ($_ =~ /e/i) && ($_ =~ /i/i) && ($_ =~ /o/i) && ($_ =~ /u/i)

    Notice how all the subsequent matches look in $_? The only reason your first example works is because the match operator defaults to matching against $_. The solution is either to bind each and every match to the variable you want to match, or to combine all the regexes into one, like so: $one_line =~ /a|e|i|o|u/i.

    Update: replies pointed out that my combined regex was not the same as the original intent.

    Update: I've posted a single-regex solution deeper in the thread. It may have problems that I'm not aware of, but seems to test out OK.

      Better would be $one_line =~ /[AaEeIiOoUu]/. There's no need to make the entire string case-insensitive - it's slower. Also, you're not doing alternation, but instead doing a character class match. Again, faster.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

        When using a range it's an OR operation, not an AND, so that will also match aaaaa eeeeee iiiiiiii, etc. I don't think that's what he was looking for. revdiablo has a good explanation.
Re: $_ works, $my_variable doesn't?
by fglock (Vicar) on Mar 31, 2004 at 17:44 UTC

    This is a cheat:

    my(@input_array) = qw(ai tyueioa ew ww ty tu aoieuyt); foreach my $one_line(@input_array) { /a/i && /e/i && /i/i && /o/i && /u/i && ( print $one_line, "\n" ) for( $one_line ); }