Lalith
Lalith

Reputation: 9

C# regex for 1,4-5,6,7-9 or 1,2,3,4-5 or 1,2-9,10-15,16

i have a text box which takes input for printing.following are acceptable patterns

1,4-5,6,7-9 or 1,2,3,4-5 or 1,2-9,10-15,16.

i tried with the following code but some cases are failing

List<bool> result = new List<bool>();
string[] array = inputstring.Split(',');
int i = 0;
foreach (string k in array)
{                            
    result.Add(Regex.IsMatch(k, @"^\d+|(\d+-\d+)$"));
    i++;
}
foreach (bool b in result)
{
    if (b.Equals(false))
    {
        MessageBox.Show("Please enter valid entry for print pages");
                                return;
    }
} 

Thanks in advance

Upvotes: 0

Views: 257

Answers (5)

MaciejLisCK
MaciejLisCK

Reputation: 3984

^(\d+(-\d+)?)(,\d+(-\d+)?)*$

Regex

NOTE: You can not validate whether first value in range is greater then second value using regexp.

Upvotes: 0

juharr
juharr

Reputation: 32296

If you need to verify that the order of the numbers is increasing and that the ranges have a start value less than the end value then you can do the following.

public static bool ValidPrintRanges(string ranges)
{
    int previousEnd = 0;
    foreach (var range in ranges.Split(','))
    {
        var pair = range.Split('-');
        int begin, end = 0;
        if (pair.Length > 2)
        {
            return false; // more than one dash
        }

        // No dash, try to parse and check to previous end
        if (pair.Length == 1)
        {
            if (!int.TryParse(range, out end)
                || previousEnd >= end)
            {
                return false;
            }
        }
        // One dash, parse both compare to each other and to previous end
        else if (pair.Length == 2)
        {
            if (!int.TryParse(pair[0], out begin)
                || !int.TryParse(pair[1], out end)
                || previousEnd >= begin
                || begin >= end)
            {
                return false;
            }
        }

        previousEnd = end;
    }

    return true;
}

Upvotes: 0

Diego Mijelshon
Diego Mijelshon

Reputation: 52735

This is not a problem that regex solves very well.

You'll see some partial solutions in other answers, but besides being hard to maintain, they won't take care of basic stuff, like validating that the page ranges make sense.

It's easier and more flexible to use a custom handler that:

  • Splits the ranges
  • Removes whitespace
  • Parses them as either single numbers or range pairs
  • Optionally, verifies that ranges are valid (a < b) and non-overlapping

Upvotes: 0

vks
vks

Reputation: 67978

^\d+(?:-\d+)?(?:,\d+(?:-\d+)?)*$

Try this.See demo.

https://regex101.com/r/iY3eK8/11

Upvotes: 1

Avinash Raj
Avinash Raj

Reputation: 174786

Seems like you want something like this,

^\d+(?:-\d+)?(?:,\d+(?:-\d+)?)+$

+ repeats the previous token one or more times.

OR

^\d+(?:-\d+)?(?:,\d+(?:-\d+)?)*$

* repeats the previous token zero or more times.

DEMO

Upvotes: 1

Related Questions