Regular expressions for beginners: patterns you will actually use
A practical introduction to regex: characters, classes, quantifiers, anchors, groups and flags, with real examples for validation, search and data cleanup.
By Toolew Team ·· 4 min read
Table of contents
Regular expressions (regex) look intimidating: a line such as ^[\w.+-]+@[\w-]+\.[a-z]{2,}$ resembles line noise. But most of what you need day to day comes from a dozen building blocks. Once you can read those, regex becomes one of the most useful tools you have for searching, validating and transforming text, in code editors, spreadsheets, command-line tools and every major programming language.
The best way to learn is to experiment. Open the Regex Tester in another tab and try each example as you read; matches are highlighted as you type.
Literal characters and the special few
Most characters match themselves. The pattern cat finds “cat” in “concatenate”. A small set of characters have special meanings and must be escaped with a backslash to match literally:
. ^ $ * + ? ( ) [ ] { } | \
So to match a full stop, write \.; to match a price such as “$5”, write \$5.
Character classes: one of several characters
Square brackets match any one character from a set:
[aeiou]matches any vowel[0-9]matches any digit;[a-z]any lowercase letter[^0-9]matches anything that is not a digit (the^negates inside brackets)
Common shorthand classes save typing:
| Shorthand | Meaning |
|---|---|
\d |
a digit, like [0-9] |
\w |
a “word” character: letter, digit or underscore |
\s |
whitespace: space, tab, newline |
\D, \W, \S |
the opposite of each |
. |
any character except a newline |
Quantifiers: how many times
Quantifiers apply to the item just before them:
*zero or more+one or more?zero or one (optional){3}exactly three;{2,4}two to four;{2,}two or more
Examples: \d+ matches a whole number of any length; colou?r matches both “color” and “colour”; \d{6} matches a six-digit Indian PIN code.
By default quantifiers are greedy: they match as much as possible. Given <b>bold</b>, the pattern <.+> matches the entire string, not just <b>. Adding ? makes a quantifier lazy (as little as possible): <.+?> matches <b> and then </b> separately.
Anchors: where the match happens
^the start of the string (or line, with the multiline flag)$the end of the string (or line)\ba word boundary
Anchors are essential for validation. \d{6} finds six digits anywhere, so “1234567” would match. ^\d{6}$ requires the entire input to be exactly six digits. Forgetting anchors is the most common reason a validation pattern accepts bad input.
\b is great for whole-word search: \bcat\b matches “cat” but not “concatenate”.
Groups and alternation
Parentheses group parts of a pattern so a quantifier can apply to all of them, and they capture what matched so you can reuse it:
(ha)+matches “ha”, “haha”, “hahaha”(jpg|png|webp)$matches file names ending in any of the three extensions;|means “or”
Captured groups are numbered from left to right. In a replacement, $1 refers to the first group. To swap “Last, First” into “First Last”, search for ^(\w+),\s*(\w+)$ and replace with $2 $1. The Find and Replace Text tool supports exactly this.
Named groups make complex patterns readable: (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) matches an ISO date and lets code refer to year, month and day. If you only need grouping without capturing, use (?:...).
Flags
Flags change how the whole pattern behaves:
gglobal: find all matches, not just the firsticase-insensitivemmultiline:^and$match at each line breaksdotall:.also matches newlinesuUnicode: required for correct handling of emoji and\p{...}classes
With the u flag, \p{L} matches a letter in any script, including Devanagari, Arabic and Chinese, which is far more inclusive than [a-zA-Z].
Patterns you will use again and again
| Task | Pattern |
|---|---|
| Trim spaces at line ends | [ \t]+$ (with m flag), replace with nothing |
| Collapse multiple spaces | {2,}, replace with a single space |
| Find blank lines | ^\s*$ (with m) |
| Indian mobile number | ^(?:\+91[\s-]?)?[6-9]\d{9}$ |
| Hex colour | ^#(?:[0-9a-fA-F]{3}){1,2}$ |
| ISO date | ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ |
The Regex Pattern Library collects tested patterns like these with explanations, and the Regex Explainer breaks any pattern you paste into plain-English pieces.
Where regex is the wrong tool
Email validation. The full email specification is so complex that a “correct” regex runs to thousands of characters. A simple pattern such as ^[^\s@]+@[^\s@]+\.[^\s@]+$ catches typos; the only real test of an address is sending a confirmation email. If you just need to pull addresses out of a block of text, the Extract Emails from Text tool handles the edge cases for you.
HTML and nested structures. Regex cannot reliably match balanced, nested tags. Use a real HTML parser.
Numbers with meaning. A regex can check that a card number has 16 digits, but not that its Luhn checksum is valid or that a date such as 31 February exists. Combine a pattern with code that checks the logic.
Avoid catastrophic backtracking
Some patterns take exponentially long on certain inputs. The classic example is nested quantifiers such as (a+)+$ run against a long string of “a” characters followed by “b”. In production code, this can freeze a server (a so-called ReDoS attack). Keep patterns specific, avoid quantifiers inside quantified groups, and test with long, non-matching input.
Practise
Regex clicks through practice, not memorisation. Take a real task, such as cleaning a CSV column, finding every phone number in a document or validating a form field, write the simplest pattern that could work, test it against both good and bad examples, and refine. Within a few sessions, those cryptic lines will start to read like sentences.
Tools mentioned in this article
Editorial team
The Toolew team builds and maintains the tools on this site and writes practical guides on using them well. Every workflow we describe is tested with the tools it mentions.