Regex not matching the string format in C#

Viewed 134

i am receiving data over serial port and i want to verify if the data format is right. the data format i am expecting is like this

number,number,number,number -> 1200,2500,6500,90

i am using the regex like this

Regex.IsMatch(s, @"^[0-4095]\,[0-4095]\,[0-4095]\,[0-4095]$")

using 4095 because the number range is between 0 and 4095. need help with this. Thanks in advance.

3 Answers

you could do it without the need to depend on regex with a simple LINQ expression and int.TryParse method:

  var sections = e.Split(',');
  sections.Count() == 4 && 
  sections.All(s => int.TryParse(s, out int i) && i >= 0 && i <= 4095);

Maybe,

^(?:40\d[0-5]|[1-3]\d{3}|\d{1,3}),(?:40\d[0-5]|[1-3]\d{3}|\d{1,3}),(?:40\d[0-5]|[1-3]\d{3}|\d{1,3}),(?:40\d[0-5]|[1-3]\d{3}|\d{1,3})$

Demo 1

might work OK, if 000,000,000,000 would be valid, otherwise,

^(?:(?:40\d[0-5]|[1-3]\d{3}|[1-9]\d{2}|[1-9]\d|\d),){3}(?:40\d[0-5]|[1-3]\d{3}|[1-9]\d{2}|[1-9]\d|\d)$

might be an option too.

Demo 2

Test

using System;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        string pattern = @"^(?:(?:40\d[0-5]|[1-3]\d{3}|[1-9]\d{2}|[1-9]\d|\d),){3}(?:40\d[0-5]|[1-3]\d{3}|[1-9]\d{2}|[1-9]\d|\d)$";
        string input = @"1200,2500,6500,90
            1200,2500,6500,90
            1200,2500,4095,90
            0,0,0,0
            999,1,0,99
            000,000,000,000
            4095,4095,4095,4095

            ";
        RegexOptions options = RegexOptions.Multiline;

        foreach (Match m in Regex.Matches(input, pattern, options))
        {
            Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
        }
    }
}

If you wish to simplify/modify/explore the expression, it's been explained on the top right panel of regex101.com. If you'd like, you can also watch in this link, how it would match against some sample inputs.


RegEx Circuit

jex.im visualizes regular expressions:

enter image description here

We cannot do range on numbers like that. You may use this regex for your use case:

^(([0-9]|[0-9][0-9]|[0-9][0-9][0-9]|0[0-9][0-9][0-9]|1[0-9][0-9][0-9]|2[0-9][0-9][0-9]|3[0-9][0-9][0-9]|40[0-9][0-5]),){3}([0-9]|[0-9][0-9]|[0-9][0-9][0-9]|0[0-9][0-9][0-9]|1[0-9][0-9][0-9]|2[0-9][0-9][0-9]|3[0-9][0-9][0-9]|40[0-9][0-5])$

Edited:

^(([0-9]{1,3}|0[0-9]{3}|1[0-9]{3}|2[0-9]{3}|3[0-9]{3}|40[0-9][0-5]),){3}([0-9]{1,3}|0[0-9]{3}|1[0-9]{3}|2[0-9]{3}|3[0-9]{3}|40[0-9][0-5])$

Or,

^(?:(?:\d{1,3}|[0-3]\d{3}|40\d[0-5]),){3}(?:\d{1,3}|[0-3]\d{3}|40\d[0-5])$

I guess you now understand the idea. To check if a number lies between 0-4095,

  • The number can be single digit 0-9
  • It can be double digit [0-9][0-9]
  • It can be any triple digit number [0-9][0-9][0-9]
  • But, for a 4 digit number, we must ignore all numbers which are greater than 4095,

    That is why the query needs to be longer than usual.

  • 1[0-9][0-9][0-9] covers all 4 digit numbers starting from 1.

...

  • 40[0-9][0-5] covers all numbers between 4000 and 4095
Related