Match a semantic version
Find semantic versions in changelogs, tags and dependency lists — MAJOR.MINOR.PATCH with optional prerelease suffixes like -rc.1.
Last updated
Matches
- 1.2.3
- 16.2.11
- 2.0.0-rc.1
Doesn’t match
- 1.2
- version two
Why it’s written this way
Three dot-separated digit runs is the semver core; the optional group tacks on a prerelease tag (-beta.2, -rc.1) using the identifier characters the spec allows.
The leading \b keeps it from starting mid-number, so the 6.2.11 inside 16.2.11 can't match on its own.
Edge cases to know
- →A four-part version (1.2.3.4) yields its first three parts as a match — extraction over text can't know where a version was supposed to end. Anchor when validating a lone field.
- →Build metadata (+20260904) isn't covered; the official full-strictness semver regex is five lines long, which is why this practical form exists.
- →A leading v (v1.2.3) is not part of the match — the version starts at the first digit.
Part by part
- \b
- A word boundary, so the version has to start at the edge of a token rather than mid-number.
- \d+\.\d+\.\d+
- The MAJOR.MINOR.PATCH core. Each component uses + rather than a fixed count, so 1.10.0 matches as readily as 1.1.0.
- \.
- An escaped dot. Unescaped, a dot matches any character at all, which is the single most common bug in version patterns.
- (?:-[0-9A-Za-z.-]+)?
- The optional prerelease suffix — the -rc.1 or -beta.2 part. The trailing ? is what makes a plain 1.2.3 still match.
Common mistakes
\d+.\d+.\d+Leaving the dots unescaped means each one matches any character, so "1x2y3" and "10203" both count as versions. It is easy to miss because the pattern still matches every real version you test it on.
\d+\.\d+\.\d+\d\.\d\.\dMatching a single digit per component works right up until a project reaches version 1.10.0, at which point it silently matches "1.10." as "1.1" and truncates your result.
\b\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?\b$Anchoring the end defeats the purpose of scanning a changelog, where versions sit mid-line. Anchors and the global flag pull in opposite directions — pick the one that matches your task.
Questions
Does this match build metadata like 1.2.3+build.7?
No. The optional group only covers the hyphenated prerelease part, so it matches "1.2.3" and stops at the plus. Add (?:\+[0-9A-Za-z.-]+)? after the prerelease group if your tags carry build metadata.
Is this the official semver regex?
No — the specification publishes a far longer pattern with named capture groups that also rejects leading zeroes such as 01.2.3. This one is the practical version for finding releases in text, where that precision costs more than it returns.
Why is there a word boundary at both ends?
Without them the pattern would happily match the "1.2.3" inside "v11.2.34", reporting a version that does not exist in the file. The boundaries make it match whole tokens only, which is what you want when scanning a changelog.
Does it match a leading v, as in v1.2.3?
Not as part of the match. The word boundary sits between the v and the 1, so scanning "v1.2.3" returns "1.2.3" without the prefix — which is usually what you want, since the v is a tagging convention rather than part of the version. Prepend v? if you need to capture it.
How do I sort the versions this finds?
Not as strings: sorted lexically, 1.10.0 lands before 1.9.0 because the character 1 precedes 9. Split each match on the dots, convert the three components to numbers, and compare them in order — or hand the list to a semver library that already does exactly that.