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

Hello,

I know it's possible to set up a range of numbers with regex.
For example: /^[0-9]/

But is it possible to set up a range of numbers higher than 9?
Like this for example: /^[250-730]/, only this doesn't work.

Thx in advance

Replies are listed 'Best First'.
Re: Range of numbers
by GrandFather (Saint) on Oct 10, 2008 at 11:01 UTC

    That does not set up a range of numbers. That sets up a character set that matches any single character of the set of characters 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9. There are various ways that you could check that a number matched in a regex is within a given range, but the best approach depends on what you are actually trying to achieve, what your knowledge level is and what the expected knowledge level of any maintenance programmer may be who comes after you.

    I'd suggest something like:

    if ($str =~ /^(\d+)/ and $1 >= 250 and $1 <= 730) { print "Matched an in range number\n"; }

    is most likely to be compatible with your currently demonstrated skill level.

    I strongly recommend that you read perlretut and perlre.


    Perl reduces RSI - it saves typing

      Or if it's part of a larger regexp where backtracking is required,

      /((?>\d+))(?(?{ $^N < 250 || $^N > 730 })(?!))/

      However, a parser is probably more appropriate at this point.

Re: Range of numbers
by psini (Deacon) on Oct 10, 2008 at 10:59 UTC

    No. [0-9] sets a set of characters, not numbers.

    Do what you want with a regex is possible but, AFAIK cumbersome: /^(2[5-9]\d|[3-6]\d\d|7[0-2]\d|730)$/ should work (not tested)

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

      I wouldn't mix ranges with numbers and \d in a regexp, unless you know your perl is older than 5.6.

      Since the previous millennium, Perl has supported Unicode in some way or another. Which means that while [0-9] matches 10 characters, \d matches many more. Several hundreds of different characters in 5.10. Your suggested pattern,

      /^(2[5-9]\d|[3-6]\d\d|7[0-2]\d|730)$/
      matches 333, 33۳ and 3۳3, but not ۳33 (۳ is Arabic 3).

        ++ Thank you for the answer. I never thought that Unicode can be an issue in recognizing numbers.

        Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

Re: Range of numbers
by holli (Abbot) on Oct 10, 2008 at 12:38 UTC
    You can abuse Regex::Assemble for this:
    use Regexp::Assemble; $re = Regexp::Assemble ->new() ->add( 250..730 ) ->re();


    holli, /regexed monk/
      Regexp::List (from the same distro) is the appropriate choice when the inputs are text strings (as opposed to regexp patterns).
      use Regexp::List qw( ); my $re = Regexp::List->new()->list2re( 250..730 );

      In Perl 5.10, the regexp engine already does that for you.

      use 5.010; # Trie alternations my ($re) = map qr/$_/, join '|', #map quotemeta, # Not needed this time. 250..730;
Re: Range of numbers
by cdarke (Prior) on Oct 10, 2008 at 12:51 UTC
    A further important point is that a character class defined inside square brackets only matches one single character in the text, so [250-370] matches either a '2', or a '5', or '0','1','2','3' (0-3), or a '7', or a '0'. To match more than one character you use a quantifier, of which + (one or more), * (zero or more), and {4} (exactly 4) are examples.
Re: Range of numbers
by johndageek (Hermit) on Oct 10, 2008 at 15:27 UTC
    if the numbers have same number of digits this could work
    #check for 257 theough 313 @aon = ("100","134","259","290","310","314","330"); foreach $n (@aon){ print "$n\n" if ($n =~ /[2-3][1|5-9][0-3|7-9]/); }

    Enjoy!
    Dageek

      Fortuitous test set...
      #check for 257 theough 313 DB<1> @aon = ("100","134","259","290","310","314","330"); DB<2> foreach $n (@aon){print "$n\n" if ($n =~ /[2-3][1|5-9][0-3|7-9]/ +)}; 259 290 310 DB<3> push @aon,"217" # should fail DB<4> print join " ",@aon 100 134 259 290 310 314 330 217 DB<5> foreach $n (@aon){print "$n\n" if ($n =~ /[2-3][1|5-9][0-3|7-9]/ +)}; 259 290 310 217 DB<6>
      This signature will be ready by Christmas
Re: Range of numbers
by marto9 (Beadle) on Oct 10, 2008 at 14:27 UTC
    Thank you for all this help.
    You guys helped me a lot. ;)