2

I need a regex code to match a set of numbers, but only if the second one is larger. The numbers appear in the format x,y, and I need to match it if y > x.

Catching numbers of any length is easy enough:

/([0-9]*),([0-9]*)/

Currently, it will catch anything in the format of x,y (if x & y are numbers). Looking at other examples out there, I tried to do something like this:

/([0-9]*),([0-9]*)(?>=\1)/

I'm pretty sure I'm in the right direction, what with the \1 there referencing the first group, but I'm not sure how to do the comparison. Can you help me?

Thanks in advance!

p.s. Here's a link to a regexr demo with some examples. As you can see, currently everything is matched.

yuvi
  • 18,155
  • 8
  • 56
  • 93
  • 5
    That can't be done with regular expressions – Philippe Leybaert May 30 '14 at 15:28
  • What language are you using? You could just capture both numbers and then use a callback to filter the results. You might also want to read a previous [answer](http://stackoverflow.com/a/17010983) of mine. – HamZa May 30 '14 at 15:29
  • Regexes are for matching patterns, not evaluating numeric values. – Andy Lester May 30 '14 at 15:30
  • @HamZa I know. but Regex will be easier for my use case as I need to pass the validation information in strings (functions and such will require pre-configuring the validation, and I need a more generic solution) – yuvi May 30 '14 at 15:30
  • @PhilippeLeybaert After seeing the [wonders you can do with regex](http://stackoverflow.com/questions/15491894/regex-to-validate-date-format-dd-mm-yyyy), I'm pretty surprised that there's no way to achieve this – – yuvi May 30 '14 at 15:32
  • 3
    Your regular expression would have to define the domain of all valid pairs of numbers. – Daniel May 30 '14 at 15:34

1 Answers1

3

regular expressions match, they do not compare

Pure regular expressions can't "compare" numbers. You would literally have to go through and make each possible scenario, similar to how you allow a range of numbers.


Here is a quick example of matching X,Y where X < Y and X < 10, you can imagine going higher than that if you want to..

\b(?:[0-9],[1-9][0-9]+|0,[1-9]|1,[2-9]|2,[3-9]|3,[4-9]|4,[5-9]|5,[6-9]|6,[7-9]|7,[8-9]|8,9)\b

Expanded Demo

Here you can see I first say that any 1 digit number [0-9] can match if the next number is [1-9] followed by at least one more digit (a number in the tens, hundreds, thousands, etc). Then we use alternation to see what each digit can be followed by (4 < [5-9]). Not only would you need to keep expanding on this if you want to go higher, but you would also need to do the inverse logic for negative numbers. This is all wrapped in a non-capturing group with word boundaries on either side.


Let's have fun and make this work for 0 <= X < 100. I still used a few short cuts:

  • [1-9][0-9],[1-9][0-9]{2,} for 10+ < 100+
  • then for each 10s I did 1[0-9],[2-9][0-9]+ for 10-19 < 20+
  • but we still need to define each ones column individually

We end up with quite a monster regex for just doing 100 numbers. Also, if you debug this you will see that the number of steps is increasing up to 500 on some of the large numbers. Here is our 951 character expression:

\b(?:[0-9],[1-9][0-9]+|0,[1-9]|1,[2-9]|2,[3-9]|3,[4-9]|4,[5-9]|5,[6-9]|6,[7-9]|7,[8-9]|8,9|[1-9][0-9],[1-9][0-9]{2,}|1[0-9],[2-9][0-9]+|21,2[2-9]|22,2[3-9]|23,2[4-9]|24,2[5-9]|25,2[6-9]|26,2[7-9]|27,2[8-9]|28,29|2[0-9],[3-9][0-9]+|11,1[2-9]|12,1[3-9]|13,1[4-9]|14,1[5-9]|15,1[6-9]|16,1[7-9]|17,1[8-9]|18,19|3[0-9],[4-9][0-9]+|31,3[2-9]|32,3[3-9]|33,3[4-9]|34,3[5-9]|35,3[6-9]|36,3[7-9]|37,3[8-9]|38,39|4[0-9],[5-9][0-9]+|41,4[2-9]|42,4[3-9]|43,4[4-9]|44,4[5-9]|45,4[6-9]|46,4[7-9]|47,4[8-9]|48,49|5[0-9],[6-9][0-9]+|51,5[2-9]|52,5[3-9]|53,5[4-9]|54,5[5-9]|55,5[6-9]|56,5[7-9]|57,5[8-9]|58,59|6[0-9],[7-9][0-9]+|61,6[2-9]|62,6[3-9]|63,6[4-9]|64,6[5-9]|65,6[6-9]|66,6[7-9]|67,6[8-9]|68,69|7[0-9],[8-9][0-9]+|71,7[2-9]|72,7[3-9]|73,7[4-9]|74,7[5-9]|75,7[6-9]|76,7[7-9]|77,7[8-9]|78,79|8[0-9],9[0-9]+|81,8[2-9]|82,8[3-9]|83,8[4-9]|84,8[5-9]|85,8[6-9]|86,8[7-9]|87,8[8-9]|88,89|91,9[2-9]|92,9[3-9]|93,9[4-9]|94,9[5-9]|95,9[6-9]|96,9[7-9]|97,9[8-9]|98,99)\b

Community
  • 1
  • 1
Sam
  • 20,096
  • 2
  • 45
  • 71
  • I don't need negative numbers or floats, and I can probably set a specific limit and it'll be ok. So yeah, that's a good answer, thank you! – yuvi May 30 '14 at 16:16
  • You can probably make some sort of for loop to automatically go through and create this string..and the higher you go the more enhancements you'll be able to do, like: `1[0-9],(?:[2-9][0-9]+|[1-9][0-9]{2,})` – Sam May 30 '14 at 16:18
  • Oh, but there's a problem (sorry to take the correct away there) - I only need say 2-3 digit numbers max. But if I use your regex on `10,20` it will match `0,20` which isn't good for me. It also matches `21,12` which is also wrong – yuvi May 30 '14 at 16:18
  • @yuvi see my update utilizing word boundaries (which does a zero-length assertion to check if a word-character is next to a non-word character `(^\w|\w\W|\W\w|\w$)`) – Sam May 30 '14 at 16:21
  • better, but now it doesn't work if the first number is two-digits. If we can use regex to [match a number higher than some arbitrary x](http://stackoverflow.com/questions/8592488/regex-how-can-i-match-all-numbers-greater-than-49), can't we use that in a more generic form? Say configure the limitations on the second number using the first number? – yuvi May 30 '14 at 16:24
  • My example was meant to match `X,Y` where `X < Y` and `X < 10`. The point is that you need to define every option, and as you get larger the expression will grow exponentially. We can't match higher than arbitrary `X` *and* make sure `Y` is higher without defining every possibility, since regex does not compare. However, I could probably type out a solution to `X < 100` if you need..... – Sam May 30 '14 at 16:26
  • Good point. Anyway, I think this is the closest I can get. I'll probably figure out the right limitations I need and use them. Thanks for your time, I really appreciate it – yuvi May 30 '14 at 16:28
  • @yuvi, just to show you how this grows exponentially, I updated my answer for `X < 100`. I'm not going any higher though (although you can see how the patterns repeat, for the ones column, and tens column, etc..so you would be able to generate a larger one somewhat easily; *not that I recommend it*). – Sam May 30 '14 at 16:38