How can I fix my regex so parameter 3 stays in capture group 3?

bot_bot :

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)

rock321987 :

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_-]+))?$

Bit of clean Solution

^(\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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=129251&siteId=1