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

Hello cellmates, I'm sitting staring at page 107 of the Learning Perl book and as far as I can see I'm doing exactly as required but....... All I want to do is ensure that a parameter supplied to a subroutine is exactly 3 digits. Nothing but numbers should be in this parameter. Easy? Well I thought so but the following example only fails if less than 3 numbers are supplied. If more than 3 numbers are supplied - even if some of the extra characters are non-digits - it passes the test!(?) Am I guily of an obvious typo or am I missing the point?
#!/usr/bin/perl -w # use strict ; # my $step = 'a123aaaa' ; # Produces True message # if ($step =~ /\d{3}/) { print "\n\tIt's true :: <$step>!\n" ; } else { print "\n\tIt's false :: <$step>!\n" ; }
This parameter must be exactly 3 characters in length and all the characters MUST be digits. What am I doing wrong? Be gentle I've already gone bald scratching my head over this one!

Replies are listed 'Best First'.
Re: Another RegExp question
by davis (Vicar) on Aug 17, 2006 at 11:20 UTC
    The regex /\d{3}/ matches 3 digits anywhere in the string. If you want to restrict it to only 3 digits, you'd need to anchor it (specify either (both in this case) "start of the string" and the "end of the string" — these are logical atomic units):
    if ($step =~ /^\d{3}$/) {

    Update: YAPE::Regex::Explain gives the following explanation:

    The regular expression: (?-imsx:^\d{3}$) matches as follows: NODE EXPLANATION ---------------------------------------------------------------------- (?-imsx: group, but do not capture (case-sensitive) (with ^ and $ matching normally) (with . not matching \n) (matching whitespace and # normally): ---------------------------------------------------------------------- ^ the beginning of the string ---------------------------------------------------------------------- \d{3} digits (0-9) (3 times) ---------------------------------------------------------------------- $ before an optional \n, and the end of the string ---------------------------------------------------------------------- ) end of grouping ----------------------------------------------------------------------

    davis
    Kids, you tried your hardest, and you failed miserably. The lesson is: Never try.
    Edited: Fixed slightly mixed tense.
      Thanks for that - guess who's feeling a tad foolish at the moment?!
        Don't - it is a common mistake.
Re: Another RegExp question
by ikegami (Patriarch) on Aug 17, 2006 at 15:17 UTC

    /^\d{3}\z/ matches exactly three digits.

    Because it's easier to read (I'm guessing), /^\d{3}$/ is commonly used. That matches exactly three digits, or exactly three digits followed by a newline.