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

$names = 'Fred Flintstone and Wilma Flintstone'; if ($names =~ m/(?<last_name>\w+) and \w+ \g{last_name}/) { print "I saw $+{last_name}\n"; }
I get the result "Flintstone". I don't understand, in the if statement, "if ($names =~ m/(?<last_name>\w+) and \w+ \g{last_name}/)" that how does it automatically match the last name, it should've matched the whole thing before "and" i.e "Fred Flintstone". Also, even when I put the * sign it still matches only "Flintstone".

Replies are listed 'Best First'.
Re: regex and matching
by CountZero (Bishop) on May 27, 2011 at 18:09 UTC
    The key to the secret is the ' and'.

    m/(?<last_name>\w+) and \w+ \g{last_name}/

    This regex matches the word (i.e. \w+ characters, this does not include whitespace!) just before the ' and' and saves it under <last_name>, and which is followed by another word and the same word as what was just saved under <last_name>.

    The only fixed point in this regex is the ' and', so it is easiest to start by this fixed point and see how the regex tries to match from there.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Hey man thanks i understood it. But i have one more problem this code:
      $flintstones = "\n or modern stoneage"; if ($flintstones =~ m/(\w*) or \w* \1/){ print "True\n"; }
      is returning true even though the conditions if ($flintstones =~ m/(\w*) or \w* \1/) is false
        You are being mislead by the evil *!

        * means= match ZERO or more of the previous character or group. In this case it is the ZERO that wins. The matched part of the string is ' or modern'.

        Try print "True/ >$1<\n"; and you will see what got matched by the first \w*.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: regex and matching
by Khen1950fx (Canon) on May 29, 2011 at 01:11 UTC
    Just to satisfy my curiosity, I tested your code against 5.8.8 and 5.10.1 using the re pragma. Under 5.8.8, it doesn't work; however, under 5.10.1, it works. Evidently, the regex engine has improved immensely. Try this and see what the result is:
    #!/usr/bin/perl use strict; use warnings; use re qw(debugcolor); my $names = 'Fred Flintstone and Wilma Flintstone'; if ($names =~ m/(?<last_name>\w+) and \w+ \g{last_name}/) { print "I saw $+{last_name}\n"; }