Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

pattern matching: why does the following code evaluate true? (and how do i fix it?)

by Buckaroo Buddha (Scribe)
on May 31, 2000 at 02:39 UTC ( #15535=perlquestion: print w/replies, xml ) Need Help??

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

$key = "INITIAL.LASTNAME,INITIAL2.LASTNAME2,INITIAL3.LASTNAME3"; $key2 = "INITIAL.LASTNAME,INITIAL2.LASTNAME2,."; if ($key =~ m/$key2/){ print " [just another perl hacker] \n"; }

  i'm cycling through two hash tables
  and trying to get the exact match but 
  it seems that i have a less than perfect 
  understanding of pattern matching

  i've got "the perl cookbook" here with me,
  so if i find the answer before this is taken 
  care of i'll post a reply to myself

  but i expected that the above statement would 
  evaluate to FALSE

  (note, i'm not actually making an attempt at a JAPH
   but i thought it was a funny replacement for 
  Execute Block ;)   

  • Comment on pattern matching: why does the following code evaluate true? (and how do i fix it?)
  • Download Code

Replies are listed 'Best First'.
Re: pattern matching: why does the following code evaluate true? (and how do i fix it?)
by btrott (Parson) on May 31, 2000 at 02:53 UTC
    That's not greedy pattern matching. That's just an example of the '.' matching any character (except newlines).

    To the OP: the regex matches because the '.' matches an "I" character. Because '.' matches anything. Read perlre.

    And try this, if you wanted a literal period ('.'):

    if ($key =~ m/\Q$key2\E/) { print " [just another perl hacker] \n"; }
Re: pattern matching: why does the following code evaluate true? (and how do i fix it?)
by Buckaroo Buddha (Scribe) on May 31, 2000 at 02:57 UTC
    so it should be:
    
    ($key =~ m/.$key2/)
    i was just about to follow up with 
    
    ($key =~ m/^$key2$/)
    as being how i solved this problem ... 
    
    (well how O'Reilly solved it)
    
    i geuss this means that the '.' in the string
    is interpreted as a wildcard matching to the 
    end of the line? 
    
    that's interesting ... please correct me if i'm wrong
    but if that's the way it works that's a really cool 
    thing to have learned  
    
       :)!
    
    
    

      The '.' matches a single character, any character, except \n (unless using the 's' modifier, to treat the expression as a single line). There are two ways to solve the problem, one is how you did it, and another is to use /\Q$key2/ as others have said, so the '.' is treated as a literal '.' (along with every other metacharacter).

      $key =~ m/^$key2$/; # works $key =~ m/\Q$key2/; # also works

      Personally I think the second option is better here. The '.' normally matches the literal '.' and anything else as well, but if your $key contained something like "INITIAL!LASTNAME" it would match if "INITIAL.LASTNAME" where the pattern. Quoting metacharacters with \Q$pattern\E is, at least, more correct, even if the first will work ok with the given input. It'll help you avoid bugs to use the second option.

      72656B636148206C72655020726568746F6E41207473754A

RE: pattern matching: why does the following code evaluate true? (and how do i fix it?)
by Adam (Vicar) on May 31, 2000 at 02:42 UTC
    Greedy Pattern Matching.
    The . matches anything (and more importantly - everything.) {Except \n}

    UPDATE: It has been pointed out to me that I am only partly correct. The dot does in fact match anything {Except \n} but it does not behave in a greedy manner. Rather, Perl is saying that the substring ($key2) is found in the other string ($key)... which is ok. I apologize if I confused anyone.

      Well, /^$key2$/, wouldn't match--there's nothing greedy in that regex. But since the pattern isn't anchored it looks for the $key2 pattern anywhere in $key.

      If you're looking for literal periods, do one of the following:

      $key2 = "INITIAL\.LASTNAME,INITIAL2\.LASTNAME2,\."; $key2 = quotemeta "INITIAL.LASTNAME,INITIAL2.LASTNAME2,."; $key =~ /\Q$key2/

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://15535]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (2)
As of 2019-08-24 07:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?