const regex = /^ # Start of version string
\s* # Ignore leading whitespace
(?:v\.?)? # Optional "v" or "v." before the version
(?<major>\d+) \. (?<minor>\d+) \. (?<patch>\d+) # MAJOR.MINOR.PATCH
(?:- # Pre-release versions start with '-'
(?<pre> # Capture the pre-release identifier(s)
(?: # The PR rules are annoyingly tight
[0-9A-Za-z-] # No leading `0`, but a `0` on its own is fine
| # More than one character...
[1-9A-Za-z-][0-9A-Za-z-]* # ...means no leading zero
) # That's the FIRST pre-release identifier
(?: # Multiple are allowed...
\. # ...dot-separated...
(?: # ...with the same rules as above
[0-9A-Za-z-]
|
[1-9A-Za-z-][0-9A-Za-z-]*
)
)* # Of course, you can also have just the one
) # End name-cap group `pre`
)? # End non-cap group encompassing the leading `-` and the identifiers
(?: # Built metadata is SIMILAR, but with two differences:
\+ # Difference one: starts with `+`
(?<meta>
[0-9A-Za-z-]+ # Difference two: leading `0` is allowed, so the match rule is simpler
(?:\.[0-9A-Za-z-]+)* # Same dot-delim repetition
) # End name-cap group `meta`
)? # End non-cap group encompassing leading `+` and identifiers
\s* # Ignore trailing whitespace
$ # End version string/gmi;
// Alternative syntax using RegExp constructor
// const regex = new RegExp('^ # Start of version string
\\s* # Ignore leading whitespace
(?:v\\.?)? # Optional "v" or "v." before the version
(?<major>\\d+) \\. (?<minor>\\d+) \\. (?<patch>\\d+) # MAJOR.MINOR.PATCH
(?:- # Pre-release versions start with \'-\'
(?<pre> # Capture the pre-release identifier(s)
(?: # The PR rules are annoyingly tight
[0-9A-Za-z-] # No leading `0`, but a `0` on its own is fine
| # More than one character...
[1-9A-Za-z-][0-9A-Za-z-]* # ...means no leading zero
) # That\'s the FIRST pre-release identifier
(?: # Multiple are allowed...
\\. # ...dot-separated...
(?: # ...with the same rules as above
[0-9A-Za-z-]
|
[1-9A-Za-z-][0-9A-Za-z-]*
)
)* # Of course, you can also have just the one
) # End name-cap group `pre`
)? # End non-cap group encompassing the leading `-` and the identifiers
(?: # Built metadata is SIMILAR, but with two differences:
\\+ # Difference one: starts with `+`
(?<meta>
[0-9A-Za-z-]+ # Difference two: leading `0` is allowed, so the match rule is simpler
(?:\\.[0-9A-Za-z-]+)* # Same dot-delim repetition
) # End name-cap group `meta`
)? # End non-cap group encompassing leading `+` and identifiers
\\s* # Ignore trailing whitespace
$ # End version string', 'gmi')
const str = `1.0.0
1.0.0-alpha
1.0.0-alpha.1
1.0.0-0.3.7
1.0.0-x.7.z.92
1.0.0-alpha+001
1.0.0+20130313144700
1.0.0-beta+exp.sha.5114f85`;
// Reset `lastIndex` if this regex is defined globally
// regex.lastIndex = 0;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for JavaScript, please visit: https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions