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

Hi all, Am beginer of learning perl. Am trying to figure it out.. how to match exactly two digits. Say i have $num = "423"; if i use if((\d\d)) { }; This will be a greedy match. How can i avoid it??
  • Comment on Is there any other way to avoid greedy matching

Replies are listed 'Best First'.
Re: Is there any other way to avoid greedy matching
by erroneousBollock (Curate) on Sep 24, 2007 at 02:55 UTC
    Say i have
    $num = "423"; if i use if((\d\d)) { };
    This will be a greedy match. How can i avoid it??
    /\d\d/ or /\d{2}/ are not greedy matches; they can only match two consecutive digit characters, so by definition they already correspond with the minimum possible length for permissible matches.

    Perhaps you misunderstand greediness. What exactly are you trying to achieve?

    Update:

    An example of a pattern where greediness causes the pattern not to match is:
       /(.*)(\d)/
    In that example, the \d will never match because .* will already have consumed the input. To make it non-greedy use
      /(.*?)(\d)/

    Update 2: Thanks ikegami, I seem to be really smoking some crack today. :-)

    -David

      Your update is completely wrong. '123' =~ /(.*)(\d)/ will match just fine. If .* matches too many characters for \d to match, backtracking will occur causing .* to match fewer characters.

      '123' =~ /(.*)(\d)/ (12)(3) '123' =~ /(.*?)(\d)/ ()(1) 'a123z' =~ /(.*)(\d)/ (a12)(3) 'a123z' =~ /(.*?)(\d)/ (a)(1)
      David.. My idea is to test if in a string are there exactly two digits are there?? like 43 or 45 or 89 or 01 or 09 etc.
Re: Is there any other way to avoid greedy matching
by krissmercedes (Initiate) on Sep 24, 2007 at 03:35 UTC
    David.. My basic idea is to see if the string has exactly two digits or not. One solution which i thought is if(^\d\d$); But is there any other way??

      /^\d\d$/ will also allow a trailing newline.
      /^\d\d\z/ checks if the string contains exactly two digits and nothing else

      Yes, there are other ways, but they are more complicated.

      If you've already verified that the string contains no non-digit characters, it's a simple as
        /^\d{2}$/

      Otherwise, something like this might work:
        scalar(() = $foo =~ /(\d)/g) == 2

      -David

      Update: Wow, what was I smoking?