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

Howdy :)

This is just something that came up in a casual email exchange today. And I've no particular reason for posing the question here other than curiosity, and perhaps providing the opportunity for those with plenty of regex fu to show their stuff :)

"How would you construct a regex to match an integer between 0 and 100?"

My regex fu is only average at best, but after a couple of minutes I came up with:

```perl -le 'for (qw/0 1 19 32.4 100 77 138 342.1/) { print "\$_ is ", /^(
+?:100|\d\d?)\$/ ? "valid input" : "invalid input"}'
Which gives:
```0 is valid input
1 is valid input
19 is valid input
32.4 is invalid input
100 is valid input
77 is valid input
138 is invalid input
342.1 is invalid input

Solves the "problem", but hard-coding the 100 in the pattern is pretty horrible, I think.

So how would others do this?

Cheers,
Darren

Replies are listed 'Best First'.
Re: Matching an integer between 0 and 100
by ikegami (Pope) on Sep 01, 2009 at 16:42 UTC

Your pattern matches 0 and 100 even though neither are between 0 and 100. Is your question wrong or is your solution wrong?

Solutions for "integers between 0 and 100":

```my \$pat = qr/
([0-9]+)
(?(?{ my \$n = \$^N; \$n <= 0 || \$n >= 100 })(?!))
/x;
```my \$pat = qr/0|[1-9][0-9]?/;
```my (\$pat) =
map qr/\$_/,
join '|',
#map quotemeta,
1..99;
```use Regexp::List qw( );
my \$pat = Regexp::List->new()->list2re( 1..99 );

Solutions for "integers from 0 to 100":

```my \$pat = qr/
([0-9]+)
(?(?{ my \$n = \$^N; \$n < 0 || \$n > 100 })(?!))
/x;
```my \$pat = qr/0|100|[1-9][0-9]?/;
```my (\$pat) =
map qr/\$_/,
join '|',
#map quotemeta,
0..100;
```use Regexp::List qw( );
my \$pat = Regexp::List->new()->list2re( 0..100 );

In all cases, you'll need to anchor the pattern as appropriate.

The first solution of each set accepts leading zeroes. Easily changed.
The bottom three solutions of each set don't accept leading zeroes. Easily changed.

Update: Oops. Accidentally omitted a "?" from my patterns.

heh... yes. The question is wrong. It should be "from" "to".
I'll blame the guy that originally wrote it ;)
Re: Matching an integer between 0 and 100
by JavaFan (Canon) on Sep 01, 2009 at 15:49 UTC
First of all, I would never ever combine \d and hardcoded numbers. Your regexp will match 0 to 99 in more than a dozen scripts, but 100 only in western numerals.

Given that, I'd write it as /^(?:[0-9]{1,2}|100)\$/. Or, if I wanted to be lazy: do {local \$" = "|"; /^(?:@{[0..100]})\$/};.

Re: Matching an integer between 0 and 100
by Anonymous Monk on Sep 01, 2009 at 17:50 UTC

I know this doesn't really answer your question, but in any real world situation, for this type of problem I'd generally solve the two criteria separately for maximum re-usability and adaptability.

Data::Validate has more robust implementations of both of these functions

```if ( is_integer(\$value) && is_between_inclusive(\$value,0,100) ){
...
}

sub is_integer{
my \$value = shift;
return \$value =~/^[-]?\d+\$/;
}

sub is_between_inclusive{
my (\$value,\$min,\$max) = @_;
return((\$value >= \$min) && (\$value <= \$max));
}