Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regular expression to match number with Decimal separator and optional Thousands separator

Tags:

regex

I need to validate if a number is valid with using decimal separator and thousand separators optionally. I need a regex, because the current code, that is not done by me uses a regex that is not working properly and I am aiming to fix it.

So the following combinations would be legal (Using . as decimal separator and , as thousand separator)

  • 10000
  • 100,000,000
  • 100,000,000.345345
  • 10000.689

But the following wouldn't be legal:

  • 10000,000,000.34534

Basically I want numbers with a proper use of decimal and thousand separator or without them at all, but not invalid combinations. I looked around a lot, so far I found this post. Which has a great regex that matches perfectly when the numbers have decimal separator and thousand separator, but when I try to add the other options (numbers only with decimal separator, or number integers) I break the expression.

I decided that maybe I could capture groups matching the rules with or, so the number matches one expression or the other like this:

^([+-]?[0-9]{1,3}(,[0-9]{3})*(\.[0-9]+)?)|(((\d)*)+?(\.\d))|(\d*)$

The first group is the expression from the other post, the second I think covers numbers with a decimal separator and the last one are integers, but it is not working.

For example these numbers are not getting matched:

  • 10000000.56
  • 10000000

I think the issue it is happening because it always test for the first group, but I am not sure how to use the groups properly so it matches either of them. Also I think I am placing the -+ signs in the wrong place.

I did search a lot, and couldn't find one expression that worked properly. From the ones suggested:

From the Regex for number with decimals and thousand separator post

  • ((\d){1,3})+([,][\d]{3})*([.](\d)*)? -> It wrongly captures 10000000. and 10,000,000.
  • ^(?!0+\.00)(?=.{1,9}(\.|$))\d{1,3}(,\d{3})*(\.\d+)?$ -> it fails for 10000000
  • /^(?!0+\.00)(?=.{1,9}(\.|$))(?!0(?!\.))\d{1,3}(,\d{3})*(\.\d+)?$/ -> it fails for 10000000
  • ((\d){1,3})+([,][\d]{3})*([.](\d)*)? -> It fails for -100.03

This Can I use an OR in regex without capturing what's enclosed? post is not a duplicate, it explains something that could help me solve the issue, but it is not a duplicate, especially because I have issues also with the +- signs. Also my questions covers a problem that is not particular to me, this is a problem many people face, yet from the implementations I have found so far, none work.

From RegEx matching numeric values with or without thousand separators post

  • ^-?([0-9]{1,3}\.?)+$ -> It fails for -1000 but not for and not for 100.00.3
  • ^-?(?!0)(?:\d+|\d{1,3}(?:\.\d{3})+)$ -> It fails for -100.03
like image 638
Dzyann Avatar asked Dec 17 '18 21:12

Dzyann


People also ask

How do you match a comma in regex?

Starting with the carat ^ indicates a beginning of line. The 0-9 indicates characters 0 through 9, the comma , indicates comma, and the semicolon indicates a ; . The closing ] indicates the end of the character set. The plus + indicates that one or more of the "previous item" must be present.

What is the thousand separator format?

The character used as the thousands separatorIn the United States, this character is a comma (,). In Germany, it is a period (.). Thus one thousand and twenty-five is displayed as 1,025 in the United States and 1.025 in Germany. In Sweden, the thousands separator is a space.


2 Answers

You may use this regex for validation:

^[+-]?(?:\d+|\d{1,3}(?:,\d{3})*)(?:\.\d*)?$

RegEx Demo

It matches following cases:

  • An integer number
  • A floating point number
  • A number with separators as , at 3rd place
like image 63
anubhava Avatar answered Oct 16 '22 03:10

anubhava


The reason the second alternative isn't matching is because it only allows a single \f after the decimal point. That needs to be \d+.

Then you need to wrap everything between ^ and $ in a group, so all alternatives match the entire string.

You had lots of redundant parentheses. And \d* in the last alternative should be \d+, otherwise you'll allow a number that's completely empty or just a sign.

^[+-]?([0-9]{1,3}(,[0-9]{3})*(\.[0-9]+)?|\d*\.\d+|\d+)$
  • ^ -> start of string
  • [+-]? -> matches optional + or - char
  • ([0-9]{1,3}(,[0-9]{3})*(\.[0-9]+)?|\d*\.\d+|\d+) -> whole group has to match [0-9]{1,3}(,[0-9]{3})*(\.[0-9]+) or \d*\.\d+ or \d+
    • [0-9]{1,3}(,[0-9]{3})*(\.[0-9]+) -> matches numbers with thousand separators and maybe decimal separator
    • \d*\.\d+ -> matches numbers with decimal separator, and maybe digits before the decimal
    • \d+ -> matches numbers without decimal separator
  • $ -> end of string

DEMO

like image 15
Barmar Avatar answered Oct 16 '22 03:10

Barmar