3

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.

2

3 Answers 3

6

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);
Sign up to request clarification or add additional context in comments.

2 Comments

After working through a two step process validating the format with Regex, then parsing the integers to check their values, I concluded this is the best answer. Regular expressions have their limits. This is a case where I don't think regex is the right answer.
agree, regex becomes hard to read pretty fast which overcome the conciseness.
2

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

1 Comment

This is really helpful !
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.