9

What is a correct regex for matching semantic versioning?

It should not match for instance

01.1.1
9.8.7-whatever+meta+meta
1.2.3.DEV
1.2.3-0123
1.0.0-alpha_beta
1.2-SNAPSHOT
1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788

it should match for instance

0.0.4
1.2.3
10.20.30
1.1.2-prerelease+meta
1.1.2+meta
1.0.0-alpha
1.0.0-alpha.beta
1.0.0-alpha.1
1.0.0-alpha.0valid
1.0.0-rc.1+build.1
1.2.3-beta
10.2.3-DEV-SNAPSHOT
1.2.3-SNAPSHOT-123
1.0.0
2.0.0+build.1848
2.0.1-alpha.1227
1.0.0-alpha+beta
1.2.3----RC-SNAPSHOT.12.9.1--.12+788
1.2.3----R-S.12.9.1--.12+meta
karlsebal
  • 1,449
  • 17
  • 23

2 Answers2

13

Take a look on the bottom of the SemVer page:

Is there a suggested regular expression (RegEx) to check a SemVer string?

^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
Orachigami
  • 416
  • 3
  • 4
  • Thank you. As this is one of the »official« ones I mark your answer as most helpful — however I am wondering why the one I found is 38 chars shorter and what I may have missed. – karlsebal Jul 07 '22 at 16:28
2

A working regex would be

^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*)(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$

Working against every flavor available at regex101.com

This is a somewhat simpler version missing the capture groups from the »official« one if you don’t need those and want to keep it simple.

karlsebal
  • 1,449
  • 17
  • 23
  • 1
    This is susceptible to a Regular Expression Denial of Service. The form `[1-9]+[0-9]*` can have polynomial runtime. Dropping the `+` and using `[1-9][0-9]*` will have identical behavior with linear runtime. – statenjason May 12 '23 at 16:55