7

I'm looking for a regex pattern that would match a version number.

The solutions I found here don't really match what I need.

I need the pattern to be valid for single numbers and also for numbers followed by .

The valid numbers are

1
1.23
1.2.53.4

Invalid numbers are

01
1.02.3
.1.2
1.2.
-1
Dharman
  • 30,962
  • 25
  • 85
  • 135
Ziko
  • 919
  • 2
  • 10
  • 22
  • 1
    Please note updates to my answer - there're a number of gotchas with parsing version formats that you might want to beware of. – Dewi Morgan Apr 09 '19 at 19:27

4 Answers4

10

Consider:

^[1-9]\d*(\.[1-9]\d*)*$

Breaking that down:

  • ^ - Start at the beginning of the string.
  • [1-9] - Exactly one of the characters 1 thru 9.
  • \d* - More digits.
  • ( - Beginning of some optional extra stuff
  • \. - A literal dot.
  • [1-9] - Exactly one of the characters 1 thru 9.
  • \d* - More digits.
  • ) - End of the optional extra stuff.
  • * - There can be any number of those optional extra stuffs.
  • $ - And end at the end of the string.

Beware

Some of this syntax differs depending what regex engine you are using. For example, are you using the one from Perl, PHP, Javascript, C#, MySQL...?

In my experience, version numbers do not fit the neat format you described.

Specifically, you get values like 0.3RC5, 12.0-beta6, 2019.04.15-alpha4.5, 3.1stable, V6.8pl7 and more.

If you are validating existing data, make sure that your criteria fit the conditions you've described. In particular, if you are following "Semantic Versioning", be aware that versions which are zeros are legal, so 1.0.1, that "Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.", and that "1" is not a legal version number.

Be warned that the above will also match stupidly long version numbers like 1.2.3.4.5.6.7.8.9.10.11.12.13.14. To prevent this, you can restrict it, like so:

^[1-9]\d*(\.[1-9]\d*){0,3}$

This changes the * for "any number of optional extra dots and numbers" to a range from zero to three. So it'd accept 1, 1.2, 1.2.3, and 1.2.3.4, but not 1.2.3.4.5.

Also, if you want zeros to be legal but only if there are no other numbers (so 0.3, 1.0.1), then it gets a little more complex:

^(0|[1-9]\d*)(\.(0|[1-9]\d*)){0,3}$

This question may also be a duplicate: A regex for version number parsing

Dewi Morgan
  • 1,143
  • 20
  • 31
  • 1
    You the GOAT. I came here again to ask about what if I want to accept 1.0.1 but refuse 1.01.1 and found that you already mentioned that in your comment. – Ziko Apr 10 '19 at 18:09
  • What regex engine are you using? It works for me, see: https://regex101.com/r/bOpKER/1 – Dewi Morgan Apr 10 '19 at 20:10
  • 1
    Nevermind for my deleted comment. I fixed it on my end – Ziko Apr 12 '19 at 14:17
6

Major.Minor.Patch - npm version like 0.1.2:

^([1-9]\d*|0)(\.(([1-9]\d*)|0)){2}$

More or optional minor groups like 1.1.5.0 or just 1.2:

^([1-9]\d*|0)(\.(([1-9]\d*)|0)){0,3}$

Avoid leading zero - no |0 in first group:

^([1-9]\d*)(\.(([1-9]\d*)|0)){0,3}$

Semantic Version String like 1.0.0-beta

^(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-]+)*))?$

Break down:

  • ^: match the line start
  • $: match the line end
  • ( and ): make a group
  • ([1-9]\d*|0): match version number
    • [1-9]\d*: starting with 1~9, following any number of digit
    • |: logical or
    • 0: literal zero
  • \.: literal (escaped) dot
  • {2}: exact 2 matches
  • {0,3}: 0~3 matches

Test cases (regex101 JavaScript):

Match:

0.0.0
0.0.1
0.1.0
1.0.0
1.0.1
1.1.0
1.1.1
0.0.10
0.10.0
10.0.0
0.1.10
1.0.10
1.0.100
0.100.1
100.0.0
1.20.0

Not match:

0.0.00
0.00.0
00.00.0
0.0.01
0.01.0
01.0.0
0.01.0
01.0.0
00.0.01
clarkttfu
  • 577
  • 6
  • 11
0

This regex should help:

^(([1-9]+\d*\.)+[1-9]+\d*)|[1-9]+\d*$

Below is the explanation.

[1-9]+\d* means a sequence which begins with a non-zero number, followed by zero or more numbers

The first part (([1-9]+\d*\.)+[1-9]+\d*) catches all of your correct examples, except of 1. So, we have a | (or), followed by a [1-9]+\d* sequence.

Ildar Akhmetov
  • 1,331
  • 13
  • 22
  • But if I test against 01, it captures the 1 so it becomes valid.. Same for 1.2., it captures the 1.2 – Ziko Apr 09 '19 at 16:33
  • Try to use the "A" ("Anchored") modifier. See the example here: https://regex101.com/r/KK0eQT/1 – Ildar Akhmetov Apr 09 '19 at 16:42
  • Thanks a lot for that. Finally, I want to know if we can generalize the rule of 0number is not valid. Example: 1.2.3.04 – Ziko Apr 09 '19 at 17:19
0

([\*,\^])([\-,\*,\w]+[\.])+(\w)*

for npm package fro example

    "cross-env": "^5.2.0",
  • 2
    Please take a moment to read through the [editing help](//stackoverflow.com/editing-help) in the [help]. Formatting on Stack Overflow is different than other sites. – Dharman Aug 28 '19 at 09:04
  • This doesn't allow a fix version like "5.2.0", it must be e.g. "^5.2.0" or "~5.2.0" – dude Jun 23 '20 at 07:13