Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex for decimals with maximum length

Tags:

c#

regex

I'm not sure if this is possible with regex. I'll try to use regex, but if not possible I'll switch to a double validation.

My database (postgresql) accepts decimal as 15,6 (Maximum of 15 digits with a maximum of 6 decimals), so if I have 10 integer digits, I can have 5 decimals digits. The decimal separator is ignored.

I currently have this regex (Comma is the decimal separator):

^\d{1,15}(\,\d{1,6})?$

It does not verify the total length, only the numbers to the left. But since the user can also type dots (thousands separator), I have this monster:

^((\d+)|(\d{1,3}(\.\d{3})+)|(\d{1,3}(\.\d{3})(\,\d{3})+))((\,\d{4})|(\,\d{3})|(\,\d{2})|(\,\d{1})|(\,))?$

This one does not accept more than 3 decimals. I can edit this one to accept 6 decimais, but I still can't validate the total length.

Is it possible to verify the total length of the number? Ignoring the dots and comma.

The regex should accept:

1234567890,123456

1.234.567.890,123456

And of course any other middle values:

1.234,12, 1,0, 1...

like image 861
Nicke Manarin Avatar asked Apr 25 '16 12:04

Nicke Manarin


3 Answers

I think you need

^(?:\d{1,3}(?:\.\d{3}){0,4}|\d{1,15})(?:,\d{1,6})?$

See the regex demo

The integer part only allows 1 to 15 digits (or 5 groups of 3-digit chunks separated with . digit grouping symbol), and optionally followed with a comma and 1 to 6 decimal digits.

  • ^ - start of string
  • (?:\d{1,3}(?:\.\d{3}){0,4}|\d{1,15}) - 2 alternatives:
    • \d{1,3}(?:\.\d{3}){0,4} - 1 to 3 digits, followed with 0 to 4 sequences of a dot (\.) and 3 digits (\d{3})
    • | - or
    • \d{1,15} - 1 to 15 digits
  • (?:,\d{1,6})? - optional sequence (1 or 0 occurrences) of a comma followed with 1 to 6 digits
  • $ - end of string
like image 83
Wiktor Stribiżew Avatar answered Oct 10 '22 14:10

Wiktor Stribiżew


Just throwing this out as an alternative. In my opinion you shouldn't use a Regex in this case. Why? Because the Regex that will actually match the question won't be easy to understand.

Much simpler solutions exist for the problem. Take for example this:

var input = "1.234.567.890,123456";
var input2 = Regex.Replace(input, @"[^\d,]+", "");

var split = input2.Split(',');
var totalLength = split[0].Length + split[1].Length;

Nothing fancy. But it works, unlike the other solutions provided until now.

But what about different culture settings? Different cultures use different thousand separators. That's where something like Double.TryParse can come in:

var input = "1.234.567.890,123456";

var style = NumberStyles.Number;
var culture = CultureInfo.CreateSpecificCulture("nl-NL");

double result;
if (double.TryParse(input, style, culture, out result))
{
    Console.WriteLine("It worked!");
}
else
{
    Console.WriteLine("Not valid");
}

The above works because the nl-NL culture uses the format. Set it to en-US and it will fail.

Neither really use a Regex to get the job done, but they can still produce the desired result.

like image 4
Chrono Avatar answered Oct 10 '22 15:10

Chrono


Try this: ^[\d\.\,]{1,15}([\.\,]\d{0,6})?$

like image 1
Huso Avatar answered Oct 10 '22 15:10

Huso