Portrait of Michael Limberger

Michael Limberger

Need me? Email mike@limberger.ca

Regex

Regex Fundamentals - Combining Patterns

How many

Now we get powerful. Quantifiers let you match repeated patterns. They modify the thing that comes before them.

Quantifier Means
* Zero or more (greedy)
+ One or more (greedy)
? Zero or one (optional)
{n} Exactly n times
{n,} At least n times
{n,m} Between n and m times

Show me.

Pattern:  ab*c
Matches:  ac, abc, abbc, abbbc (zero or more b's)

Pattern:  ab+c
Matches:  abc, abbc, abbbc (one or more b's, NOT ac)

Pattern:  ab?c
Matches:  ac, abc (zero or one b only)

Pattern:  a{3}
Matches:  aaa (exactly three a's)

Pattern:  a{2,4}
Matches:  aa, aaa, aaaa (two to four a's)

Numbers you actually type

Phone numbers, simple:

Pattern:  \d{3}-\d{3}-\d{4}
Matches:  123-456-7890

Variable length words: \w+ is one or more word characters. Optional country code: \+?\d{10,11} matches 1234567890 or +12345678901. The question mark makes the plus sign optional.

Greedy versus lazy

By default, quantifiers are greedy. They match as much as possible.

Given text: <title>Hello</title>

Pattern:  <.*>
Matches:  <title>Hello</title> (the whole thing!)

That is often not what you want. Add ? to make it non-greedy:

Pattern:  <.*?>
Matches:  <title> (stops at first >)

*? is zero or more, lazy. +? is one or more, lazy. ?? is zero or one, lazy. The difference matters when you are extracting data.

The pipe is OR

The pipe character means "or":

Pattern:  cat|dog
Matches:  "cat" or "dog"

Pattern:  gray|grey
Matches:  Both spellings

Pattern:  red|green|blue
Matches:  Any of the three colors

Parentheses group

Parentheses group patterns together. Three jobs.

Apply quantifiers to groups: (ab)+ matches ab, abab, ababab.

Alternation groups: gr(a|e)y matches gray or grey.

Capturing for later use (more in the rename section): (hello) (world) captures "hello" in group 1, "world" in group 2.

Group without capturing

Sometimes you need grouping but do not need to capture:

Pattern:  (?:ab)+
Groups "ab" but does not capture it.

Use (?: ) when you only need grouping for logic, not extraction.

Word boundaries

The \b anchor matches the boundary between a word and a non-word character.

Pattern:  \bcat\b
Matches:  "cat" but NOT "category" or "concatenate"

Pattern:  cat
Matches:  cat, category, concatenate (anywhere "cat" appears)

Word boundaries are essential for precise matching.

An email-shaped example

Not a production validator. Just how pieces combine:

Pattern:  \w+@\w+\.\w+

Symbol map: \w+ is one or more word characters (username). @ is a literal at-sign. \w+ is the domain. \. is a literal dot. \w+ is the TLD.

Dates

YYYY-MM-DD: \d{4}-\d{2}-\d{2} matches 2024-01-15, 2023-12-31. More flexible, allowing single digits: \d{4}-\d{1,2}-\d{1,2} matches 2024-1-5 and 2024-01-15.