Published
Regular expressions for everyday text jobs
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:
- i: case-insensitive, so
catmatches Cat and CAT. - g: global, find every match rather than stopping at the first.
- m: multiline, so
^and$match at the start and end of every line rather than the whole text.
Mistakes that trip people up
- Forgetting to escape the dot.
example.comalso matches examplexcom, because.means any character. Writeexample\.com. - Unanchored validation.
\d{4}finds four digits inside "12345". To require exactly four digits and nothing else, use^\d{4}$. - Dialect differences. JavaScript, Python, Go and text editors each support slightly different features. Lookbehinds and named groups in particular vary. Test in the same flavour you will run.
- Parsing HTML with regex. Fine for a one-off clean-up. For anything real, use a proper parser.
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.