20

I'm currently using ([1-9]|1[0-2]) to represent inputs from 1 to 12. (Leading zeros not allowed.)

However it seems rather hacky, and on some days it looks outright dirty.

☞ Is there a proper in-built way to do it?

☞ What are some other ways to represent number ranges?

Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • 2
    If "Bigger is better", then (1|2|3|4|5|6|7|8|9|10|11|12) would be better. – Ingo Aug 18 '11 at 09:50
  • 4
    You need to wrap the expression with anchors, otherwise you will match the first digits of an erroneous value like `1234`. Something like this: `^([1-9]|1[0-2])$` or possibly: `\b([1-9]|1[0-2])\b` will work better. – ridgerunner Aug 20 '11 at 19:10

9 Answers9

18

I tend to go with forms like [2-9]|1[0-2]? which avoids backtracking, though it makes little difference here. I've been conditioned by XML Schema to avoid such "ambiguities", even though regex can handle them fine.

xan
  • 7,511
  • 2
  • 32
  • 45
  • Basically, when the matcher sees a "1" character, the "meaning" is ambiguous until it sees more characters. Is it the "1" for [1-9] or the "1" for 1[0-2]? Regex doesn't care about meaning, but it's still sometimes an efficiency concern since the matcher has to keep both branches active until the ambiguity is resolved. – xan Aug 21 '11 at 14:19
  • so you are saying in the eyes of the regex machine this is the fastest solution: 1|2|3|4|5|6|7|8|9|10|11|12 ? – Pacerier Aug 22 '11 at 01:12
  • No, I'm not comparing `[2-9]` with `2|3|4|5|6|7|8|9` -- don't know which is faster. I'm comparing `1|10` with `10?`. Not that it will make a matter for such a trivial example, but for more involved regexes, it will help to remove common prefixes of branches. Perhaps a better example: `ab|ac` improved to `a(b|c)`. – xan Aug 22 '11 at 02:45
  • In my case, numbers under 10, should have a leading zero, so i changed the pattern as follows `0[1-9]|1[0-2]?` – pho Jun 24 '20 at 12:04
  • 2
    This expression also accepts numbers like 123, you can test it here https://regexr.com/5hjpc, the idea is to test only numbers from 1 - 12 not more not less – Diego Alberto Zapata Häntsch Dec 03 '20 at 20:26
  • 1
    @DiegoAlbertoZapataHäntsch so, something like this: `/^([2-9]|1[0-2]?)$/` – Bob Brown Feb 23 '21 at 22:34
  • @BobBrown it doesn't work you can test your expression in these links https://regexr.com/5hk0s and https://regexr.com/5hkae to confirm that it doesn't work as expected. – Diego Alberto Zapata Häntsch Feb 23 '21 at 23:26
14

Yes, the correct one:

[1-9]|1[0-2]

Otherwise you don't get the 10.

Ingo
  • 36,037
  • 5
  • 53
  • 100
9

Here is the better answer, with exact match from 1 - 12.

(^0?[1-9]$)|(^1[0-2]$)

Previous answers doesn't really work well with HTML input regex validation, where some values like '1111' or '1212' will still treat it as a valid input.

Kimman wky
  • 101
  • 1
  • 2
5

​​​​ You can use:

[1-9]|1[012]
Pacerier
  • 86,231
  • 106
  • 366
  • 634
codaddict
  • 445,704
  • 82
  • 492
  • 529
3

How about:

^[1-9]|10|11|12$

Matches 0-9 or 10 or 11 or 12. thats it, nothing else is matched.

Blackpanther0001
  • 258
  • 1
  • 3
  • 14
2

You can try this:

^[1-9]$|^[1][0-2]$
2

Use the following pattern (0?[1-9]|1[0-2]) use this which will return values from 1 to 12 (January to December) even if it initially starts with 0 (01, 02, 03, ..., 09, 10, 11, 12)

gleisin-dev
  • 150
  • 1
  • 15
1

The correct patter to validate numbers from 1 to 12 is the following:

(^[1-9][0-2]$)|(^[1-9]$)

The above expression is useful when you have an input with type number and you need to validate month, for example. This is because the input type number ignores the 0 in front of any number, eg: 01 it returns 1.

You can see it in action here: https://regexr.com/5hk0s

if you need to validate string numbers, I mean, when you use an input with type text but you expect numbers, eg: expiration card month, or months the below expression can be useful for you:

((^0[1-9]$)|(^1[0-2]$))

You can see it in action here https://regexr.com/5hkae

I hope this helps a lot because it is very tricky.

Regards.

-3

In python this matches any number between 1 - 12:

12|11|10|9|8|7|6|5|4|3|2|1

The descending order matters. In ascending order 10, 11 and 12 would match 1 instead as regex usually pick the first matching value.

Aram Maliachi
  • 215
  • 2
  • 8