I have the following regex expression:
^(\d*)(?:\.)(\d*)(?:|(?:\.)(\d*))(?:|(?:\.)([a-zA-Z0-9_-]*))?$
You can test it here.
I want to use it to parse a version number into groups, for example (where g1 is the group number 1 and so on):
1.2 => g1(1),g2(2)
1.2.3 => g1(1),g2(2),g3(3)
1.2.3.4_or_text => g1(1),g2(2),g3(3),g4(4_or_text)
This almost works, except if the third group is optional, and skips to the fourth group if the version has 3 parts.
So what actually happens is this:
1.2 => g1(1),g2(2)
1.2.3 => g1(1),g2(2),g3(),g4(3) <-- I want to fix this
1.2.3.4_or_text => g1(1),g2(2),g3(3),g4(4_or_text)
I can't pinpoint what I'm doing wrong.
The way it is working now also means that the following is valid: 1.2.3_or_text
since that is parsed as g1(1),g2(2),g3(),g4(3_or_text)
You are having extra alternation(|)
expression in your regex
^(\d*)(?:\.)(\d*)(?:|(?:\.)(\d*))(?:|(?:\.)([a-zA-Z0-9_-]*))?$
^ ^
this this
It tells to match nothing which always passes. As a result your second part of alternation never matches.
Further explanation: Alternation syntax is like
(?:a|b|c)
In your case a
is nothing, that's why its always true and matches
Correct Solution: You are also missing optional group and assuming there should be at least one digit or alphabet, this should be correct regex
^(\d+)(?:\.)(\d+)(?:(?:\.)(\d+))?(?:(?:\.)([a-zA-Z0-9_-]+))?$
^(\d+)[.](\d+)(?:[.](\d+)(?:[.]([\w-]+))?)?$
Regex Breakdown
^ #Start of string
(\d+)[.] #Match digit and dot
(\d+) #Match next group
(?: #Non-capturing group
[.](\d+) #Match dot and digit
(?:[.]([\w-]+))? #Match dot and digit. This is optional
)? #Third and Fourth match can be optional
$ #End of string