liveBook · Manning

Regex grouping

As explained in The Well-Grounded Rubyist, Fourth Edition

A submatch is the substring matched by a parenthesized subpattern within a regular-expression match.

Suppose a string contains a last name, first name, title, and occupation, separated by commas. A regular expression can establish that the fields match the expected pattern; parentheses let you keep just the fields you need. In `/([A-Za-z]+),[A-Za-z]+,(Mrs?\.)/`, the first group captures the last name and the second captures the title. section 11.4.1

Extract two fields

For `m = /([A-Za-z]+),[A-Za-z]+,(Mrs?\.)/.match("Peel,Emma,Mrs.,talented amateur")`, `m[0]` is the entire matched portion, `"Peel,Emma,Mrs."`; `m[1]` is `"Peel"`, and `m[2]` is `"Mrs."`. Ruby also makes those captures available as `$1` and `$2`. A failed `match` returns `nil`, so check for a match before querying it. section 11.4.1 section 11.4.2

Capture numbers follow opening parentheses from left to right, even when groups are nested. With `/((a)((b)c))/` matched against `"abc"`, captures 1 through 4 are `"abc"`, `"a"`, `"bc"`, and `"b"`. `m.captures` returns them as an array starting at index 0, whereas `m[1]` is the first capture; `m[-1]` retrieves the last. section 11.4.3

Choose a grouping form according to what you need afterward:

  • Use `(?<first>\w+)` to name a capture; retrieve it with `m[:first]` or inspect `m.named_captures`. An optional group that does not match can have a `nil` value. section 11.4.3
  • Use `(?:...)` when parentheses should group and match characters without saving another numbered capture. Unlike a lookaround assertion, this group consumes characters. section 11.5.3

Captures remain useful beyond a single match. `scan` collects repeated matches with captures into arrays of captured fields, or passes each result to a block. In `sub` and `gsub`, a replacement string can refer to captures as `\1` and `\2`; a block can instead use `$1` and `$2`. Do not interpolate `$1` into a replacement string expecting each substitution to refresh it: that string may use a capture from an earlier match. Ruby’s numbered capture variables are thread-local. section 11.7.1 section 11.7.3 section 14.5.4

How The Well-Grounded Rubyist, Fourth Edition covers it

How deep it goes
Works through numbering, nested and named groups, optional captures, non-capturing groups, and retrieval through MatchData.
Examples
Uses comma-separated personal fields, a phone number, nested groups, scanned names, and a corrected letter transposition.
What it assumes
Assumes familiarity with Ruby strings and basic regex matching, then teaches parenthesized captures from a concrete pattern.
What you can do after
Applies it via Ruby’s match, scan, sub, and gsub to extract fields and reuse captures in replacements.
How it connects
Connects regex grouping to MatchData, named captures, lookaround assertions, String#scan, and string substitution.

Also explained in

Compare how 6 books explain regex grouping →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Rubyist, Fourth Edition. The section links point to the parts of the book it draws on.