Writing

What Is a Regular Expression?

A regex is a pattern that matches text: find every email address, every date, every duplicated word. The syntax that covers most real uses, and where it goes wrong.

· 3 min read

What Is a Regular Expression?

In short

A regular expression is a pattern describing a set of strings, used to search, match or replace text. Instead of searching for one exact word, you describe a shape: any digit, any run of letters, anything between two brackets. Most practical uses need only a dozen symbols, and nearly every text editor and programming language supports them.

A regular expression, almost always shortened to regex, is a way of describing text by its shape rather than its exact contents. Ordinary search finds a word you already know. A regex finds every date, every email address, every line ending in a question mark, without you knowing any of them in advance.

The idea

Searching for cat finds cat. A regex lets you search for the pattern instead: three letters, or any word ending in at, or a word that appears twice in a row.

That change is what makes it useful for cleaning data, validating input, and the sort of find-and-replace that would otherwise take an afternoon of manual editing.

The symbols worth learning

A dozen cover most real work.

PatternMatches
.Any single character
\dAny digit
\wAny letter, digit or underscore
\sAny whitespace
*Zero or more of the previous item
+One or more of the previous item
?Zero or one, making it optional
{3}Exactly three
{2,5}Between two and five
[abc]Any one of a, b or c
[^abc]Any character except those
^Start of the line
$End of the line
()A group, which can be captured and reused

Uppercase versions of the shorthand classes invert them: \D is any non-digit, \S any non-whitespace, \W any character that is not a letter, digit or underscore.

Reading a real pattern

A UK postcode, loosely:

[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}
  • One or two capital letters
  • A digit
  • Optionally another letter or digit
  • An optional space
  • A digit
  • Two capital letters

Read left to right, each piece describing one part of the shape. That is all any regex is, however intimidating a long one looks.

Capture groups and replacement

Brackets capture part of a match so you can reuse it. This is where regex earns its keep in find-and-replace.

To convert dates from 2026-09-30 to 30/09/2026:

  • Find: (\d{4})-(\d{2})-(\d{2})
  • Replace: $3/$2/$1

The three groups are numbered in the order their opening brackets appear, and the replacement puts them back in a different arrangement. In some tools the placeholder is \1 rather than $1.

Greedy versus lazy

A trap that catches everyone exactly once.

.* is greedy: it matches as much as it possibly can. Applied to <b>one</b> and <b>two</b> looking for <b>.*</b>, it matches the entire string, because the final </b> is still a valid ending.

Adding a question mark makes it lazy: <b>.*?</b> stops at the first possible ending and matches only <b>one</b>.

When a pattern matches far more than expected, greediness is almost always the reason.

Everyday uses

  • Find duplicated words: \b(\w+)\s+\1\b finds the the and and and, which spellcheckers routinely miss because both words are spelled correctly.
  • Collapse multiple spaces: find \s{2,} and replace with a single space.
  • Strip trailing whitespace: find \s+$ and replace with nothing.
  • Find empty lines: ^$.
  • Extract numbers: \d+(\.\d+)? matches integers and decimals.
  • Reformat a list: wrap each line by finding ^(.+)$ and replacing with <li>$1</li>.

The escaping rule

Characters with special meaning must be escaped with a backslash to match literally. Those are:

. ^ $ * + ? ( ) [ ] { } |

An unescaped full stop matches any character, so searching for file.txt also matches fileXtxt. Writing file\.txt fixes it.

This is the single most common beginner error and it produces matches that look almost right, which is exactly why it survives review and reaches production.

Where regex is the wrong tool

Anything with nesting. HTML, JSON, source code and mathematical expressions all contain structures that can contain themselves to arbitrary depth, and regular expressions provably cannot handle that.

A pattern that appears to extract HTML tags works on simple cases and fails on nested or malformed ones, usually in production rather than in testing. Use a parser built for the format.

Regex is for flat patterns within a line: a date, a reference number, a field in a log entry, a duplicated word.

Working safely

  • Test on a copy before running a replacement across real files. An over-greedy pattern can destroy a document in one keystroke and there is rarely an undo that reaches far enough.
  • Build the pattern in pieces, checking each addition against sample text rather than writing the whole thing and debugging it afterwards.
  • Comment complex patterns where the tool allows it, because a regex you wrote three months ago is effectively someone else’s work.
  • Prefer several simple passes over one clever pattern. Two readable replacements beat one unreadable one, and they fail more obviously when they fail.

Anchors, boundaries and the difference between them

Two constructs that look similar and behave differently.

Anchors match positions in the line: ^ is the start, $ is the end. They match no characters at all, which is why ^$ finds an empty line.

Word boundaries, written \\b, match the position between a word character and a non-word character. Searching for cat finds it inside concatenate; searching for \\bcat\\b finds only the standalone word.

That distinction is what makes find-and-replace safe. Replacing cat with dog across a document also rewrites concatenate. Replacing \\bcat\\b does not, and it is worth adding by reflex.

Common questions

Are regular expressions the same in every program?

Mostly, with differences at the edges. The core syntax is shared, but there are several dialects. JavaScript, Python, PCRE and POSIX differ over lookbehind support, named groups and some shorthand classes. A pattern that works in one usually works in another with small adjustments.

How do I match a literal full stop?

Escape it with a backslash. An unescaped full stop matches any character at all, which is the single most common beginner mistake. The same applies to other special characters such as brackets, plus signs and question marks.

When should I not use a regex?

For parsing structured formats with nesting, such as HTML, JSON or source code. Those need a real parser, because nesting is precisely what regular expressions cannot handle reliably. Use them for flat patterns within a line.

Sources

Every factual claim above traces to one of these. Follow them rather than taking this article's word for it.

  1. Regular expressions MDN Web Docs

Try it yourself

Free, instant, and nothing you enter leaves your browser.