Agreeing with all the caveats that validation via regular expression is not the way, we can ramble on the subject.
It's hard to remember, just because you can do, it does not mean it should
I'll repeat the warning , because it costs nothing to alert:
You have the gun, I give you the ammunition, but you decide whether to shoot your own leg or not.
The @JJao's answer is about closed intervals. I've read that at your comments you quote that the range is open. So, I ponder, how should it be for open ranges?
Let's talk here first in unit intervals, then extrapolate to any interval.
Open at the upper limit
The first case is if the upper limit is opened. For example, the range [42, 43)
accepts the value 42.999999
, but not 43.000000
.
To recognize this interval, with six decimal places, there is no secret. Just extrapolate the idea of @JJaoao to the desired number.
42(\.[0-9]{1,6})?
This expression is closed at the lower bound is opened at the top. Accepts from 42
to 42.999999
, as 42.0000
, but does not accept 43
.
Open at lower limit
And the lower limit? It was easy on the upper bound, will it also be on the bottom?
For this, we need to recognize any string after the .
that contains at least a nonzero number, limited to 6 numbers.
Basically this is the same question of generating a 1 to 6 digit string where at least one of these digits is nonzero. I got this to answer, I could not simplify. I separated the alternatives below, the answer would be to put them all interspersed with |
.
[1-9][0-9]{0,5}
0[1-9][0-9]{0,4}
0{2}[1-9][0-9]{0,3}
0{3}[1-9][0-9]{0,2}
0{4}[1-9][0-9]{0,1}
0{5}[1-9]
In a way, for a total of% with% decimal places at the most, beginning with% zeros on the left, the formula for creating these subexpressions is:
0{z}[1-9][0-9]{0,m-z-1}
Being m
, with z
and 0 <= z <= m - 1
nonnegative integers.
So, to recognize a number in the lower open range (and only lower), the regex would be somewhat large. For z
, it would be:
42\.([1-9][0-9]{0,5}|0[1-9][0-9]{0,4}|0{2}[1-9][0-9]{0,3}|0{3}[1-9][0-9]{0,2}|0{4}[1-9][0-9]{0,1}|0{5}[1-9])|43(\.0{1,6})?
If it were opened at both ends, the expression would not have to consider the integer m
at the end:
42\.([1-9][0-9]{0,5}|0[1-9][0-9]{0,4}|0{2}[1-9][0-9]{0,3}|0{3}[1-9][0-9]{0,2}|0{4}[1-9][0-9]{0,1}|0{5}[1-9])
Joining consecutive intervals
Well, we start with unit intervals, which start in whole numbers. And what would be the union of these intervals if they are consecutive?
The first alternative would be to put the expressions of each interval grouped between (42,43]
43
and interspersed with (
.
But we could do better, would not we?
The best-behaved interval is the closed range at the lower limit but open at the upper bound. It contains a constant part (the integer part of the number) followed by the following expression:
(\.[0-9]{1,6})?
When we are interspersing several of these ranges, just put this expression on the right side and on the left side the constants separated by )
or some other expression that refers to this. For example, |
can be represented as:
(3[2-9]|4[0-3])(\.[0-9]{1,6})?
On the right side, the magic expression that represents the unit interval closed at the lower limit but open at the upper limit. On the right side, an expression representing all integers in the past range.
If you need to deal with a closed range at the upper bound, simply add the limit value followed by 0 to 6 zeros. As if it were a union between the closed interval at the beginning but open at the end and the individual number: |
42(\.[0-9]{1,6})?|43(\.0{1,6})?
The other unions can continue to be applied normally, so doing [32,43)
is doing [42,43) U {43}
:
(3[2-9]|4[0-3])(\.[0-9]{1,6})?|43(\.0{1,6})?
For open interval, however, the formula will get large. I do not go by what the expression would look like here, it would be illegible of any sort. The thought, however, would be to isolate a single open unit interval at both ends, then treat the rest as closed intervals at the lower bound and open at the upper. Type, [32, 43]
can be interpreted as [32,42) U [42,43) U {43}
, or else as (32,43]
.