2

I need regular expression for numbers that can be negative, with commas or decimal.

For examples: 12 +12 -12.0 -12,345.5466 +12,345,678,678 0.154

But not pass: "500." or "500,". I want that 500 will return as a number without the point or the comma that connect to the number.

The regular expression that I wrote is:

[-+]?((0|([1-9](\d*|\d{0,2}(,\d{3})*)))(\.\d*[0-9])?)(?!\S)

It is work at the correct numbers (like the examples), but It don't work for the '500,' or '500.'

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563

1 Answers1

1

Assuming you want to match 500 in 500. and 500,, you should bear in mind that (?!\S) requires a whitespace or end of string immediately to the right.

You may fix the problem with

[-+]?(?:0|[1-9](?:\d{0,2}(?:,\d{3})*|\d*))(?:\.\d+)?(?!\d)

See this regex demo, and note that this can be further enhanced depending on what contexts you need to exclude.

I replaced (?!\S) with (?!\d) at the end to fail the match if there is a digit, not any non-whitespace char, immediately on the right.

Note also that I removed unnecessary groups and converted all capturing groups to non-capturing.

Also, pay attention to the (?:,\d{3})*|\d*) group, where I swapped the alternatives since the first one is more specific and should go first.

Details

  • [-+]? - an optional - or +
  • (?:0|[1-9](?:\d{0,2}(?:,\d{3})*|\d*)) - 0 or
    • [1-9] - a non-zero digit
    • (?:\d{0,2}(?:,\d{3})*|\d*) - either
      • \d{0,2}(?:,\d{3})* - zero, one or two digits, and then zero or more occurrences of a comma and three digits
      • | - or
      • \d* - zero or more digits
  • (?:\.\d+)? - an optional sequence of . and one or more digits
  • (?!\d) - a negative lookahead that fails the match if there is a digit immediately to the right of the current location.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thank you very mach. I have one more question. if I want that but not to sepeatae % from the number, like 500% ? – lirongr1996 Oct 28 '21 at 16:23
  • @lirongr1996 It [already handles](https://regex101.com/r/rLhPkt/2) `500%`. Only `500` is matched. – Wiktor Stribiżew Oct 28 '21 at 16:24
  • I understand. Do you konw how the expression like '12,34.54' or '0.15,4' or '5,6+78' will not pass ? – lirongr1996 Oct 28 '21 at 16:37
  • @lirongr1996 Because these are not correct numbers. `12,34.54` is `12` and `34.54`. `0.15,4` is a `0.15` and `4`. And `5,6+78` contains three matches. – Wiktor Stribiżew Oct 28 '21 at 16:44
  • Yes, that what I meant. How those expression not pass at all ? It consider the expression as whole and not dismantled, because there is no space. – lirongr1996 Oct 28 '21 at 17:00
  • @lirongr1996 I do not understand what you mean by "not pass". Regex either matches a string or not. The regex I shared matches exactly as I explained. If you need specific behavior, please explain what you expect to obtain for each string. – Wiktor Stribiżew Oct 28 '21 at 17:01
  • @lirongr1996 Did my answer resolve your original issue? What is that you are trying to achieve? – Wiktor Stribiżew Oct 28 '21 at 17:11
  • Yes, it resolve the original issue perfect. I want those expression not match at all because they are not correct numbers. for example '12,34.54' not match because there isn't 3 digit after the comma, or '5,6+78' not match because there is + in the middle, or if there is '-+1' also not match. Thank you very very mach for your help – lirongr1996 Oct 28 '21 at 17:25
  • @lirongr1996 I think I understood: these strings you posted are standalone strings, and not space separated. You need a pattern like `^[-+]?(?:0|[1-9](?:\d{0,2}(?:,(?:\d{3})*)*|\d*))(?:\.\d*)?$`, see [this regex demo](https://regex101.com/r/rLhPkt/3). – Wiktor Stribiżew Oct 28 '21 at 17:28
  • No, thank you so mach for your help – lirongr1996 Nov 10 '21 at 08:18