Regexdrill

Groups and lookarounds Updated November 2026

Capture groups

Parentheses group part of a pattern and capture what it matched: (\d{4})-(\d{2}) stores the year in group 1 and the month in group 2. Groups let you apply a quantifier to a sequence, (ab)+, reuse the text with $1 in a replacement or \1 in the pattern, and read it from match()[1] in JavaScript.

Syntax

(pattern)      read: match[1], m.group(1)      reuse: $1 in replacements, \1 in the pattern

Examples

"2024-03".match(/(\d{4})-(\d{2})/)

Result: ["2024-03", "2024", "03"]

Index 0 is the whole match, then the groups in order.

"John Smith".replace(/(\w+) (\w+)/, "$2, $1")

Result: "Smith, John"

[..."a=1, b=2".matchAll(/(\w)=(\d)/g)].map(m => [m[1], m[2]])

Result: [["a", "1"], ["b", "2"]]

matchAll gives every match with its groups.

/^(ab)+$/.test("ababab")

Result: true

The group lets + repeat the whole sequence.

Common mistakes

  • Calling str.match with the g flag and expecting groups; it returns only the full matches. Use matchAll or exec.
  • Writing \1 in a replacement string; JavaScript replacements use $1, while \1 belongs inside the pattern.
  • Miscounting groups: they are numbered by the position of the opening parenthesis, including nested ones.
  • Repeating a group, (\d)+, and expecting all iterations; a group keeps only its last match.

Practice Capture groups

These drills check your answer on live data, free, no account needed.

  • Capture a standalone yearCapture the first standalone four-digit number on each line in group 1. Digits that are part of a longer number do not count. Lines without one give no match.
  • Repeated group: dotted numbersThe whole line must match. Match one or more numbers separated by single dots, like 1, 1.2 or 10.0.3. No leading, trailing or doubled dots.
  • Swap Last, First to First LastLines that are exactly Last, First become First Last. Names contain letters, apostrophes and hyphens. Leave other lines unchanged.

Questions

How do I get a captured group in JavaScript?

const m = str.match(re); m[1] is the first group, or null if there was no match. With the g flag use [...str.matchAll(re)] and read m[1] on each item.

What is group 0?

The whole match. match()[0] and Python's m.group(0) return the full matched text; numbered groups start at 1.

How many capture groups can I have?

Practically unlimited, but $10 and above work only when at least ten groups exist, and large group counts hurt readability. Switch to named groups beyond three or four.

Related

  • Non-capturing group (?:...)How (?:...) groups for quantifiers and alternation without a numbered capture, why that keeps group numbers stable, and how it changes findall in Python.
  • Named groups (?<name>...)How to capture by name, read match.groups.name, use $<name> in replacements and \k<name> as a backreference, and the (?P<name>) syntax Python needs.
  • Backreferences \1What \1 means, finding doubled letters and repeated words, matching a closing quote equal to the opening one, and \1 in a pattern versus $1 in a replacement.
  • match, test, replace in JavaScriptWhich JavaScript regex method to use for a yes/no check, the first match, all matches with groups, substitution and splitting, with return values and g rules.

Previous: Unicode regexNext: Non-capturing group (?:...)