2

I have been trying to solve the following issue:

  1. Match all numbers in range 20 to 999
  2. Increments of 5
  3. No decimal point
  4. Greater or equal to 20.

Upon research came up with the following:

(?=^([2-9]\d|[1-9]\d{2,})$)(?=^\d*[05]$) 

(strangely, in the regex tester I am using, the expression doesn't always work).

or

(?=^[2-9]\d+)(?=\d*[05]$)

I think this case the range is limited 20 to 99 only.

Can you help, please?

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
  • Which language/tool are you using? Also, please use comparison operator to check the range of number instead of using regex. It's much less prone to bug and the code is more maintainable. – nhahtdh Nov 11 '15 at 10:03
  • This match is related to the selection of the number of cores in a specific application. I think the format of the regex is javascript, at least that the option I have been using, (also in the regex tester) and so far it has been working for other regex expressions used. – Francisco Ramilo Nov 11 '15 at 10:07
  • What [about this](https://regex101.com/r/uK8pO5/1) `^(?:[2-9]|[1-9]\d)[05]$` – bobble bubble Nov 11 '15 at 10:13
  • I think you meant this: `^(?=\d*[05]$)([2-9]\d|[1-9]\d{2})$` The answers have shown that you don't need lookaheads, but if you did, you would only need one. And only one start anchor, *outside* the lookahead. But the only critical error was the comma in `\d{2,}`. That part was supposed to match two digits exactly, not two or more. – Alan Moore Nov 11 '15 at 15:45

2 Answers2

4

Assuming the string contains only the number, and leading zeros are not allowed:

^([2-9]|[1-9]\d)[05]$

Constructing the regex is not too hard, just consider the ranges:

  • From 20 to 99 with increment of 5, the regex for this range would be [2-9][05]
  • From 100 to 999 with increment of 5, the regex for this range would be [1-9]\d[05]

It's considerably easy in this case, since all valid values in each multiple of 10s or 100s are within the range.

An example of harder case would be the range from 25 to 260 inclusive of both ends with increment of 5. We need to break it into the following ranges to reduce the problem to writing regex for all values within multiple of 10s/100s:

  • The value 25
  • The range from 30 to 99: [3-9][05]
  • The range from 100 to 199: 1\d[05]
  • The range from 200 to 250: 2[0-5][05]
  • The value 260
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
  • Thanks guys, much appreaciated! – Francisco Ramilo Nov 11 '15 at 11:26
  • A quick question, what if, as I think you were going with the last portion of the code, ranges 30 to 99, 100 to 199, etc.. the range wasn't limited to 999? So starting from 20, increments by value of 5 also what if no leading zeros were allowed? – Francisco Ramilo Nov 12 '15 at 11:10
  • @FranciscoRamilo You always want to match numbers that end in 0 or 5 so your regex suffix will always be: `[05]`. It is the prefix that will change. I've tried to give a clear explanation of how the prefix is being created in [my (very similar) answer](http://stackoverflow.com/a/33671034/2642059). – Jonathan Mee Nov 12 '15 at 12:21
  • @FranciscoRamilo: If from 30 to inf., increment by 5, no leading zero, then `[3-9][0-5]` for 30 to 99, and `[1-9]\d{2,}` for 100 to inf. – nhahtdh Nov 13 '15 at 04:18
2

Try this: (\d{2}|[2-9])[05]
The problem with your solution is that you don't check if you have a 2-digit or 3-digit number.

My solution says the following:

  • (<X>|<Y>) - Match either X or Y (not both)
  • \d{2} - Exactly 2 digits
  • [2-9] - Exactly one digit in the range of 2-9
  • [05] - a '0' or a '5' (multiply of 5)

As a whole it says "a 3-digit number, or a 2-digit number where the first digit is 2-9, and the last digit is 0 or 5".

This should work as long as you don't have leading zeroes. In that case, you'll need a lookahead and it'll be more complicated.

YMI
  • 165
  • 1
  • 10