Published

Regular expressions for everyday text jobs

A dark monitor showing lines of colour-highlighted code
Photo by Chris Ried on Unsplash

Regular expressions have a reputation for being unreadable, and long ones are. But most everyday jobs need only a small part of the syntax: find every email address in a document, collapse double spaces, swap the order of a date, pull the numbers out of a list. Learn a dozen pieces and you can do all of those in seconds.

The pieces that do most of the work

Pattern Matches
abc The literal text abc
. Any single character
\d A digit, 0–9
\w A letter, digit or underscore
\s A space, tab or line break
[abc] Any one of a, b or c
[^abc] Any character except a, b or c
^ and $ The start and end of a line
* Zero or more of the previous thing
+ One or more
? Zero or one, so optional
{2,4} Between two and four
( ) A group you can refer back to

Characters with a special meaning, such as ., ?, ( and +, need a backslash to match literally: \. matches a full stop.

Example: collapse repeated spaces

Text pasted from PDFs is often full of double spaces. Find:

 {2,}

That is a space followed by {2,}, meaning two or more spaces. Replace with a single space. Use \s{2,} instead to also catch tabs, but note that it will join lines too, since line breaks count as whitespace.

Example: find email addresses

A simple pattern that catches almost every real address:

[\w.+-]+@[\w-]+\.[\w.-]+

Read it piece by piece: one or more letters, digits, dots, plus signs or hyphens; an @; a domain name; a dot; the rest of the domain. It will accept a few oddities that are not valid addresses, and the full email specification is far more complicated, but for pulling addresses out of a document it is the right trade-off. Do not use a regex alone to validate addresses at sign-up; sending a confirmation email is the only real test.

Example: reformat dates

Groups let you capture parts of a match and reuse them in the replacement. To turn US-style 10/18/2026 into ISO 2026-10-18:

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

The three groups capture month, day and year, and $1, $2 and $3 put them back in a new order. Some tools write the references as \1 instead of $1.

This also shows a limit: the regex has no idea whether 10/11/2026 is October 11th or 10 November. It just moves the digits. Only use it when you know which format the data is in.

Example: pull numbers out of text

To find every price in a block of text, including decimals:

\d+(\.\d+)?

One or more digits, optionally followed by a dot and more digits. Add \$ at the front to match only dollar amounts, and ,? patterns for thousands separators if the text uses them.

Greedy versus lazy

By default * and + are greedy: they match as much as they can. On the text <b>one</b> and <b>two</b>, the pattern <b>.*</b> matches the whole line, from the first <b> to the last </b>.

Adding ? makes them lazy, matching as little as possible. <b>.*?</b> matches <b>one</b> and then <b>two</b> separately. This one change fixes a large share of "my regex matched too much" problems.

Flags

Flags change how the whole pattern behaves. The common ones:

Mistakes that trip people up

Try it

The regex tester highlights every match and capture group in your own text, and can explain a pattern in plain English, which is the fastest way to learn what each piece does. If you would rather not write the pattern at all, the regex generator has ready-made patterns for emails, URLs, dates and phone numbers, or builds one from sample strings. For find-and-replace across a block of text with group references, use regex replace, and keep the regex cheat sheet open for the syntax you only use twice a year.

More from the blog

← All posts