I\'m searching for a pattern for the following behavior:
number1-number2
number1: Can be everything >= 0 and <= int.MaxValue
number2: Can be everything >
Solution
It is possible to test it using regex - but you should prefer a solution in code because it will be much faster. This regex needs a lot of backtracking. The only advantage of this regex is that it works for an arbitrary number length.
(?:^0+-\d+$)
|
(?:^(?>0*)(?<number>\d+)-(?>0*)\k<number>$)
|
(?:
(?:^(?>0*)(?<length>\d)+-(?>0*)(?<-length>\d)*(?(length)(?!))\d+$)
|
(
(?=^(?>0*)(?<o>\d)+-(?>0*)(?<-o>\d)*(?(o)(?!))$)
^
(?>0*)
(?<prefix>\d*)
(?:(?<g0>0)|(?<g1>1)|(?<g2>2)|(?<g3>3)|(?<g4>4)|(?<g5>5)|(?<g6>6)|(?<g7>7)|(?<g8>8)|(?<g9>9))
\d*
-
(?>0*)
\k<prefix>
(?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!))))))))))
\d*
$
)
)
This matches for every x-y
where x <= y
for positive integer numbers including leeding zeros.
DEMO
It doesn't work for chars.
Explanation
I was able to create a regex that matches x-y
for all x < y
. The question was x <= y
. So I splitted the question to x = y | x < y
.
We need to handle that the first or both numbers does only contain zeros but that's trivial:
^0+-\d+$
Now the case x = y
^(?>0*)(?<number>\d+)-(?>0*)\k<number>$
The tricky part is x < y
.
x
is smaller than y
if x
is shorter in char length than y
(leeding zeros are captured by an atomic group):
^(?>0*)(?<length>\d)+-(?>0*)(?<-length>\d)*(?(length)(?!))\d+
This first group captures the whole number by one capture per digit. After the separator a balancing group definition clears the capture stack and forces at least one more digit.
Both numbers are of the same length (if the first number is longer it is also greater and should not match).
To ensure that both numbers are of the same length I started with a positive look behind assertion that ensures it the same way I tested for a longer number in step 1:
(?=^(?>0*)(?<o>\d)+-(?>0*)(?<-o>\d)*(?(o)(?!))$)
After that the algorithm is simple. Start at the beginning. If the current digit is equal go to the next digit. If the current x
-digit is slower than the current y
-digit we're finished and a match is found. If it's slower we should not match. This is done by that pattern:
^
(?>0*) # cut out leeding zeros
(?<prefix>\d*)
.*
-
(?>0*) # cut out leeding zeros
\k<prefix> # both numbers start with the same part
.*
$
And now the check for one digit. There are only 10 possibilities [0-9]. Each of them is captures by a single group:
(?<g0>0)|(?<g1>1)|(?<g2>2)|(?<g3>3)|(?<g4>4)|(?<g5>5)|(?<g6>6)|(?<g7>7)|(?<g8>8)|(?<g9>9)
Now we're able to use conditions to check whether the current y
-digit is greater then the current x
-digit. Lets show for 0 and 1:
(?<g0>0)|(?<g1>1)
: If a 0 matches for the current x
-digit there are only [1-9]
for the current y
-digit. If 1 matches only [2-9]
is able. This could be used in a condition:
(?(g0)[1-9]|...)
what means if g0
has a capture [1-9]
has to match otherwise the rest has to match. This is combined to:
(?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!))))))))))
The last trick is that none of the groups g[0-8]
has been matched only g9
is available and there is no greater digit possible and the match should fail (?!)
.
This all has been combined to the whole regex that matches x-y
for all x <= y
.
Regex can only be used to match the numbers. Post that a comparison operation needs to be done.
string num="number1-number2";//where (number1 & number2)=numeric val
MatchCollection stringVal= Regex.Matches(num,@"\d+");
int num1=Convert.ToInt32(stringVal[0].Value);
int num2=Convert.ToInt32(stringVal[1].Value);
if(num1>=0 && num1<=int.MaxValue && num2>=num1 && num2<=int.MaxValue)
return true;
else
return false;
will give you an array containing the the numbers
You cannot use a regex for comparing extracted numbers. You need to parse the values with int.TryParse
and implement other checks to get what you need.
Assuming you only have integer positive numbers in the ranges, here is a String.Split
and int.TryParse
approach:
private bool CheckMyRange(string number_range, ref int n1, ref int n2)
{
var rng = number_range.Split('-');
if (rng.GetLength(0) != 2)
return false;
if (!int.TryParse(rng[0], out n1))
return false;
if (!int.TryParse(rng[1], out n2))
return false;
if (n1 >= 0 && n1 <= int.MaxValue)
if (n2 >= n1 && n2 <= int.MaxValue)
return true;
return false;
}
And call it like
int n1 = -1;
int n2 = -1;
bool result = CheckMyRange("1-2", ref n1, ref n2);