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

Hi, This problem seems to be very easy but stiil I am having problem.I am reading a variable and then I am trying to vallidate that it's a two digit number and less than or equal to 10.But it's working for only the number which is 10. here is the code.Please suggest something
if(($totalNumber =~ /^\d{2}$/){ if($totalNumber <= 10){ print "the number is less than 10\n"; } }

Replies are listed 'Best First'.
Re: vallidating a regular expression
by davido (Cardinal) on May 11, 2006 at 07:06 UTC

    I read that you're trying to validate that you've received a two-digit number, less than or equal to ten. That means to me you're looking for 01, 02, 03, 04, 05, 06, 07, 08, 09, and 10, and that you want to REJECT 1, 2, 3, 4, 5, 6, 7, 8 and 9. In other words, it appears by the way you've worded your question, and by the way that you've constructed your regular expression, that the leading '0' is significant to you.

    Perl, on the other hand, is happy to convert strings to numbers (if it can), and numbers to strings. That's helpful sometimes, and other times it might just get in your way. Here's the issue: Let's say you start with a string, "01", and then you perform some operation on it whence Perl must treat that string as a number. That's fine, but once it's been treated as a number, Perl no longer cares that it at one time had a leading zero. This is because, numerically, 01 is the same as 1, and thus, once treated as a number, that leading zero loses significance and *poof*, it's just gone.

    Now, we don't see in your example code where $totalNumber comes from. And we don't see how you've treated it within your script. My suspician is that though you may at one point have had yourself a nice "01" string, you performed some operation that resulted in the string being taken as a number, so the leading '0' disappears.

    If, on the other hand, you don't care about that leading '0', your regexp should probably just be written like this:

    m/^\d{1,2}$/

    Also, the text your script prints errantly reports that with an input of 10 (ten), "the number is less than 10". It should say, "the number is less than or equal to ten\n".


    Dave

      Good points from davido
       
      and,
      <demi-hemi-semi-joke> does "-10" or "1.2" also qualify? After all, neither the minus nor the decimal point is a "number." </demi-hemi...>

      and <serious point>: the OP's exact language definitely countenances any 2-digit number (where "number"'s meaning is roughly eq "value") equal to or less than 10. But it does NOT rule out the possibility that the data may contain three digit numbers, such as "007" nor single-digit numbers, like "4;" negative values such as "-10" (<BTW>Does the sign in a signed decimal count as a "digit' for OP's intended purpose?) or -- for that matter -- (hex) 0x0a (which, last time I checked) is less than 0x10. Indeed the discussion would have quite different parameters had OP used "2 digit numeral" ( ?? which would mean unicode ?!) or "two numeral value" instead of "number."</point>

      So, <peroation>1. gentle readers, perhaps the imprecision in OP's post and the wisdom in some of the replies (notably, that of reasonablekeith, who says he is neither and that cited above) will remind all who visit here, that snippet samples of data and desired outcomes can help those who would help you.

      1. Devil's Dictionary

Re: vallidating a regular expression
by bobf (Monsignor) on May 11, 2006 at 06:53 UTC

    The regex /^\d{2}$/ specifies exactly 2 digits (see perlre for more information about using curlies as quantifiers). Changing it to /^\d\d?$/, which means one digit followed optionally by another digit, or /^\d{1,2}$/, which specifies either one or two digits, give the results you want.

    Note that this regex works only for integers. Numbers containing decimal points (such as 2.0) will fail.

    Additionally, there is an extra opening parenthesis in your 'if' statement. use warnings; would have alerted you to the syntax error.

Re: vallidating a regular expression
by GrandFather (Saint) on May 11, 2006 at 07:11 UTC

    Matching one of two patterns eases the problem:

    use strict; use warnings; while (<DATA>) { if (/^(10|\d)$/) { print "Match for $_"; } else { print "Rejected $_"; } } __DATA__ 0 1 9 10 11 20 99 100

    Prints:

    Match for 0 Match for 1 Match for 9 Match for 10 Rejected 11 Rejected 20 Rejected 99 Rejected 100

    Update: substituting /^0*(10(\.0+)?|\d(\.\d+)?)$/ for the regex allows leading zeros and decimal fractions. With the test data:

    0.1 01 1 1.0 1.01 9.9 10 10.0 10.01 11 20 99 100

    the code prints:

    Match for 0.1 Match for 01 Match for 1 Match for 1.0 Match for 1.01 Match for 9.9 Match for 10 Match for 10.0 Rejected 10.01 Rejected 11 Rejected 20 Rejected 99 Rejected 100

    DWIM is Perl's answer to Gödel
Re: vallidating a regular expression
by Samy_rio (Vicar) on May 11, 2006 at 06:59 UTC

    Hi s_gaurav1091, If I understood your question correctly then here is my try,

    $totalNumber = sprintf "%02d", 1; if($totalNumber =~ /^\d{2}$/){ if($totalNumber <= 10){ print "the number is less than 10\n"; } }

    If you assign two digit integer with preceding zero to the variable then that variable doesn't hold the preceding zero. Since your first condition fails. See below,

    $totalNumber = 01; print $totalNumber;

    Regards,
    Velusamy R.


    eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';

Re: vallidating a regular expression
by reasonablekeith (Deacon) on May 11, 2006 at 09:07 UTC

    Your question is a perfect example of why you should provide a working example when asking questions on SOPW

    I'm assuming you're doing something like this...

    my @test_numbers = qw(1 2 5 8 10 12 14 56); foreach my $test_number (@test_numbers) { if( $test_number =~ /^\d{2}$/){ if($test_number <= 10){ print "$test_number\n"; } } }
    If that assumption is correct, then as already mentioned, your single digit numbers are not passing your regex because you've mandated that there must be two characters.

    this is a simple fix to the regex, combined with getting rid of your nested if statement you get the following.

    foreach my $test_number (@test_numbers) { if( $test_number =~ /^\d{1,2}$/ and $test_number <= 10){ print "$test_number\n"; } } __OUTPUT__ 1 2 5 8 10
    but without knowing exactly what your data was, it's hard to say if this is right for you.
    ---
    my name's not Keith, and I'm not reasonable.
Re: vallidating a regular expression
by smokemachine (Hermit) on May 11, 2006 at 13:00 UTC
    could be somethink like this?
    perl -e 'for(@ARGV){print"$_\n"if/^(\d{1,2})$/&&$1<=10}' 1 2 5 8 10 12 + 14 56
Re: vallidating a regular expression
by ruzam (Curate) on May 11, 2006 at 16:34 UTC
    For all the answers given here, as far as I can see your script does exactly what you asked it to do:

    a) Validate that it's a two digit number
    b) The number is less than or equal to 10

    If you're expecting results other than '10' then must look at what the contents of $totalNumber is coming into the script, or redefine your problem (to say allow single digits, leading zeros, decimal points, negative signs, etc).
Re: vallidating a regular expression
by TedPride (Priest) on May 11, 2006 at 07:37 UTC
    print "the number is less than 10\n" if $totalNumber =~ m/(\d+)/ && length($1) == 2 && $1 <= 10;
A reply falls below the community's threshold of quality. You may see it by logging in.
A reply falls below the community's threshold of quality. You may see it by logging in.