WierdX — Programming Reference All tutorials →
Developer reference · Practical tutorials · CS fundamentals
Tools & Techniques

Regular Expressions Explained

Regular expressions look cryptic until you understand the small grammar behind them. This guide breaks that grammar down into pieces you can combine and reuse.

Published April 16, 2026

A regular expression (regex) is a pattern that describes a set of strings. The regex engine tests whether a string matches the pattern, and optionally tells you where and what it matched. They appear in almost every programming language and many command-line tools (grep, sed, awk).

Literals and the dot

The simplest regex is a literal string. /cat/ matches any string that contains the three characters c, a, t in sequence. A dot . matches any single character except a newline:

/c.t/   matches "cat", "cut", "c3t", "c t"
        does NOT match "ct" (nothing between c and t)

To match a literal dot, escape it: \.

Character classes

Square brackets define a set of acceptable characters at one position:

[aeiou]      matches any single vowel
[0-9]        matches any digit (same as \d)
[a-z]        matches any lowercase letter
[^aeiou]     matches any character that is NOT a vowel
[a-zA-Z0-9]  matches any alphanumeric character

Shorthand classes are available in most flavours:

\d   digit [0-9]
\w   word character [a-zA-Z0-9_]
\s   whitespace (space, tab, newline)
\D   non-digit
\W   non-word character
\S   non-whitespace

Quantifiers

Quantifiers control how many times the preceding element must appear:

?   zero or one   — makes the element optional
*   zero or more
+   one or more
{3}   exactly 3
{2,5} between 2 and 5 (inclusive)

Example: /colou?r/ matches both "color" and "colour" because u? means the u is optional.

By default, quantifiers are greedy — they match as much as possible. Add ? after a quantifier to make it lazy (match as little as possible):

Input:  "<b>hello</b> and <b>world</b>"
Greedy  /<b>.*<\/b>/   matches the whole string (from first <b> to last </b>)
Lazy    /<b>.*?<\/b>/  matches "<b>hello</b>" then "<b>world</b>" separately

Anchors

Anchors don't match characters — they match positions:

^   start of the string (or line in multiline mode)
$   end of the string (or line)
\b  word boundary (between a \w and a \W character)
\B  non-word boundary

/^\d{5}$/ matches exactly a five-digit string (a US ZIP code) and nothing else, because it must start and end the string.

Groups and capturing

Parentheses group part of a pattern and capture what they match:

/(\d{4})-(\d{2})-(\d{2})/

Applied to "2026-04-16", this captures three groups: "2026", "04", "16". Most regex APIs let you retrieve groups by index or name:

# Python
import re
m = re.match(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})', '2026-04-16')
print(m.group('year'))   # "2026"
print(m.group('month'))  # "04"

Use (?:...) for a non-capturing group when you need grouping for alternation or quantifiers but don't want to capture the content.

Alternation

The pipe | means "or". /cat|dog/ matches "cat" or "dog". Wrap in a group when alternation is only part of a larger pattern: /I have a (cat|dog)/ matches "I have a cat" or "I have a dog".

Practical patterns developers use

# Email (simplified — full RFC is impractical as regex)
/^[^\s@]+@[^\s@]+\.[^\s@]+$/

# URL slug
/^[a-z0-9]+(?:-[a-z0-9]+)*$/

# IPv4 address
/^(\d{1,3}\.){3}\d{1,3}$/

# Hex colour code
/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/

# Strip leading and trailing whitespace
/^\s+|\s+$/g

# Extract all numbers from a string
/\d+/g

Common mistakes

Forgetting to escape special characters is the most common error. In a regex, these characters have special meaning and must be escaped with a backslash if you want to match them literally: . * + ? ^ $ { } [ ] | ( ) \

Writing overly complex regex when a simple string split or library function is clearer. Regex is powerful but not always the best tool. Validating an email address properly should use a dedicated library, not a 100-character regex pattern that still misses edge cases.

The best way to learn regex quickly is to use an interactive tester. Paste a pattern and test strings, see what matches and what doesn't, and observe how changing the pattern affects results. The feedback loop is far faster than reading documentation in isolation.