Groups and alternation
Use parentheses to group sub-patterns for quantifiers and the pipe operator to match one of several alternatives.
- Group a sub-pattern with parentheses so a quantifier applies to the whole group
- Use | to match one of several alternatives
- Predict how alternation interacts with the rest of the pattern
Two tools dramatically expand what patterns can express: grouping with
parentheses (…) and alternation with the pipe |. Together they let you say
"match any one of these complete phrases" or "repeat this multi-character sequence."
Grouping with (…)
Without parentheses, a quantifier applies to only the single atom immediately before it:
/ab+/.test("ab"); // true — 'a' once, 'b' one or more times
/ab+/.test("ababab"); // true — 'a' once, then many b's... actually:
// matches "ab" at start (a then b+)Wait — let's be precise. /ab+/ means a followed by one-or-more bs. It does
not mean "ab repeated." To repeat the pair ab, wrap it in a group:
/(ab)+/.test("ab"); // true — "ab" once
/(ab)+/.test("ababab"); // true — "ab" three times
/(ab)+/.test("aabb"); // false — not "ab" repeatedGroups create a unit that a quantifier treats as a single atom:
/(ha)+/.test("hahaha"); // true — "ha" repeated
/(\d{3}-)+/.test("555-666-"); // true — "NNN-" repeated twiceCapturing vs non-capturing
By default (…) is a capturing group — it records the matched text so you can
retrieve it from the result. The intermediate tier covers this in depth. For now,
just know that the parentheses serve two purposes: grouping (this lesson) and
capturing (later).
If you only want grouping without capturing, use (?:…) — also covered in the
intermediate tier.
Alternation with |
The pipe | means "match either the expression on the left or the one on the
right":
/cat|dog/.test("I have a cat"); // true
/cat|dog/.test("I have a dog"); // true
/cat|dog/.test("I have a fish"); // falseAlternation has very low precedence — lower than concatenation. This means
/cat|dog food/ means cat OR dog food, not cat food OR dog food. Groups
fix that:
/(cat|dog) food/.test("cat food"); // true
/(cat|dog) food/.test("dog food"); // true
/(cat|dog) food/.test("bird food"); // falseWithout the group: /cat|dog food/.test("cat") is true because the left branch
cat matches on its own.
Multiple alternatives
You can chain as many alternatives as you need:
/Mon|Tue|Wed|Thu|Fri/.test("Meeting on Wed"); // true
/^(GET|POST|PUT|DELETE|PATCH)\s/.test("POST /api/users"); // trueThe engine tries each alternative from left to right and returns on the first
match. If you have /a|ab/ and the input is "ab", the engine matches "a"
and stops — it never reaches ab. Order matters when one alternative is a
prefix of another.
Alternation inside a larger pattern
Alternation inside a group participates naturally in the surrounding pattern:
// Match both "colour" and "color"
/colou?r/.test("colour"); // true — simpler with ?
/colo(u|)r/.test("colour"); // true — alternation approach
/colo(u|)r/.test("color"); // true
// Match "Mr", "Mrs", or "Ms"
/^(Mr|Mrs|Ms)\.?\s/.test("Mrs. Smith"); // true
/^(Mr|Mrs|Ms)\.?\s/.test("Dr. Smith"); // falseGroups with quantifiers — practical examples
// US phone: (555) 123-4567 or 555-123-4567
/(\(\d{3}\)|\d{3})[-\s]\d{3}-\d{4}/.test("(555) 123-4567"); // true
/(\(\d{3}\)|\d{3})[-\s]\d{3}-\d{4}/.test("555-123-4567"); // true
// Repeated domain labels: "sub.example.com"
/(\w+\.)+\w+/.test("sub.example.com"); // true
/(\w+\.)+\w+/.test("example.com"); // trueWhere to go next
Next: the dot and flags — understanding . in depth, and the five flags that
change how the engine interprets a pattern.