Reputation: 17900
I need for my current project to parse and validate numeric expressions, similar to those used in CSS3's :nth-child()
. Basically, the expression is an+b
, where a
and b
must be integer values (both positive and negative). They can also be equal to 0
.
Some examples to make everything more clear: 2n+1
, 2n
, 4
and n+2
should be valid. Basically, a
and b
are any kind of integers, signed or unsigned.
The following examples:
n (a=1, b=0)
n+1 (a=1, b=1)
1 (a=0, b=1)
2n+1 (a=2, b=1)
23n+45 (a=23, b=45)
2n-2 (a=2, b=-2)
-1 (a=0, b=-1)
-2n (a=-2, b=0)
are all valid. This should fail only when a
or b
is not an integer, or if some other character is present in the expression.
I would like to know how can I parse and validate these expressions; I believe a suitable solution would be REGEXes, but I have no idea how can I build one for this.
Upvotes: 0
Views: 158
Reputation: 6721
EDIT: revised to allow negative numbers as specified in the question END EDIT
If these are valid values:
5n+12 3456 -5 2 123n+6 8n 13n-6 n+2
And these are invalid:
25n.1 4x+4 2n+ 6N-2 8n-+5 n+-3 Rn+T x+1
then this expression should validate:
^(-?\d+(n([+-]\d+)?)?)$
This expression says:
^ # Assert beginning of line
(\d+ # Match one or more digits
(n # TRY to Match a literal n character
(\+\d+ # TRY to match a literal plus character followed by one or more digits
)? # END TRY
)? # END TRY
) # End Match
$ # Assert at end of string
The TRY
s will attempt to validate, but will not mind if it is not there.
EDIT:
Though the above expression should validate, this expression should produce precisely the results you seek, using named capturing groups a
and b
, and a positive lookahead to capture only the numbers for a
and b
and to exclude the +
symbol, but only capture the -
symbol for negative numbers:
^(?:(?:(?P<a>-?\d*)n)?(?=[+-]?\d+|$)\+?(?P<b>-?\d+)?)$
Results should be as follows:
source a b
------ ------ ------
5n+12 5 12
3456 3456
2 2
123n+6 123 6
8n 8
-5 -5
13n-6 13 -6
n+2 2
n
Because I am not completely sure how the <null value or nothing>
vs ,zero length or null string>
dichotomy works in PHP and preg_match_all
, I would recommend using this expression if you encounter any problems differentiating between the results for n+2
and 2
:
^(?:(?P<n>(?P<a>-?\d*)n)?(?=[+-]?\d+|$)\+?(?P<b>-?\d+)?)$
This captures the entire "n" expression or nothing if there is none, for n+2
, 2
, and 12n+2
, this produces:
source n a b
------ ------ ------ ------
2 2
n+2 n 2
12n+2 12n 12 2
Upvotes: 3
Reputation: 887459
You want something like ^(?:(?:(-?\d*)n)?([+-]\d+)?|(\d+))$
.
This will return the two numbers in the two successful capture groups.
Upvotes: 1