Before this lesson

Understand character classes, quantifiers and greedy matching. Be able to inspect exec results.

What you will be able to do

Extract fields and distinguish captures from grouping-only constructs.

Understand the mechanism

(a|b) scopes alternatives inside a group. ^cat|dog$ means starts with cat or ends with dog, unlike ^(?:cat|dog)$. Check the alternative scope before the anchors.

Ordinary parentheses create numbered captures, (?:...) groups without capturing, and (?<name>...) creates a named capture. Named fields reduce maintenance errors when group numbering changes.

A match does not finish semantic validation. This version pattern accepts unsigned integers without multi-digit leading zeros. Parsed numbers still need project-specific limits to stay within safe-integer range.

Runnable example

const version = /^v(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)$/;
const match = version.exec("v12.3");
console.log(JSON.stringify(match ? [match.groups.major, match.groups.minor] : null));
console.log(version.test("v01.3"));
console.log(/^(?:cat|dog)$/.test("catfish"));
console.log(/^(?<word>[a-z]+)-\k<word>$/.test("go-go"));

Trace and verify

Named captures return the strings 12 and 3. v01.3 and catfish are rejected. The named backreference requires the second word to repeat the first, accepting go-go.

Common mistakes and boundaries

Guard against null before accessing groups. A backreference repeats captured text, not the subpattern with arbitrary new text.

Practice challenge

Add a patch field so v12.3.0 passes and v12.3 fails.

Reference solution and reasoning

Add \.(?<patch>0|[1-9]\d*) before the end anchor. All three captures remain strings; validate ranges before numerical conversion.

Further reading