Regex for Beginners: 15 Patterns You Will Actually Use (With Plain-English Explanations)

14 min readUpdated November 2026Developer Guides

Regular expressions have a reputation for looking like a cat walked across the keyboard. The truth is that a small set of building blocks covers most of what you will ever need, and once you can read them, a single pattern can replace twenty lines of string-handling code.

What a regex is and when to reach for one

A regular expression, or regex, is a compact way of describing a pattern of text. You give the engine the pattern and some text, and it tells you whether the text matches, where the matches are, and what pieces were captured. Almost every programming language supports them, and so do code editors, command-line tools such as grep and sed, and many spreadsheet and database tools.

Regex shines for three kinds of job:

  • Validating that something looks right, such as a date, postcode or slug.
  • Extracting the parts you care about from messy text, such as order numbers in an email or links in a page.
  • Replacing patterns in bulk, such as stripping extra spaces or reformatting dates across a file.

The best way to learn is to experiment. Open the Regex Tester in another tab, paste some sample text and try each pattern in this guide as you read. Seeing the matches highlight in real time teaches faster than any explanation.

The building blocks

Almost every pattern is built from the same few ideas. Learn these and you can read most expressions you meet.

Literals and character classes

TokenMeaningExample
abcThe exact text “abc”matches “abc” in “abcdef”
.Any single character except a newlinec.t matches “cat”, “cot”, “c9t”
\dA digit, 0 to 9\d\d matches “42”
\wA letter, digit or underscore\w+ matches “user_1”
\sWhitespace: space, tab, newlinea\sb matches “a b”
[abc]Any one of the listed charactersgr[ae]y matches “gray” and “grey”
[a-z]Any character in a range[A-Z] matches one capital letter
[^abc]Any character not listed[^0-9] matches a non-digit

The capital forms are the opposites: \D is a non-digit, \W a non-word character and \S a non-space character.

Quantifiers: how many times

TokenMeaning
*Zero or more
+One or more
?Zero or one (optional)
{3}Exactly 3
{2,5}Between 2 and 5
{2,}2 or more

Anchors and groups

  • ^ marks the start and $ the end of the text (or of a line, in multiline mode).
  • \b marks a word boundary, the invisible edge between a word character and a non-word character.
  • ( ) groups part of a pattern and captures the text it matched. (?: ) groups without capturing.
  • | means “or”. cat|dog matches either word.
  • \ escapes a special character, so \. matches a literal dot and \( a literal bracket.

Reading a pattern, piece by piece

When a pattern looks scary, split it into tokens and read left to right. Here is a pattern for an ISO date such as 2026-11-05, broken into its parts.

Anatomy of \d{4}-\d{2}-\d{2} \d{4} – \d{2} – \d{2} 4 digits: the year 2 digits: the month 2 digits: the day matches 2026-11-05
Figure 1. Splitting a pattern into tokens turns a cryptic string into three plain-English instructions. Note that it checks the shape of a date, not whether the date exists.

15 patterns you will actually use

Each of these is a practical starting point. Test them against your own data, because real-world text always has surprises.

1. Find all numbers

\d+

One or more digits in a row. For decimals, use \d+(?:\.\d+)?, which allows an optional dot followed by more digits.

2. Match a whole word only

\bcat\b

Matches “cat” in “the cat sat” but not in “category” or “concatenate”. Word boundaries save you from accidental partial matches.

3. An ISO date

\d{4}-\d{2}-\d{2}

The pattern from Figure 1. To also check that months run from 01 to 12 you can use \d{4}-(?:0[1-9]|1[0-2])-\d{2}.

4. A hex colour code

#(?:[0-9a-fA-F]{3}){1,2}\b

Matches “#fff” and “#1A5A6F”. The group repeats either once (three digits) or twice (six digits). The Color Converter turns what you find into RGB or HSL.

5. A simple email shape

[^\s@]+@[^\s@]+\.[^\s@]+

Some text without spaces or @ signs, then @, then more text, a dot and more text. This is deliberately loose. The full email specification is surprisingly complex, and a stricter regex usually rejects valid addresses. The reliable test is to send a confirmation email.

6. A web address

https?:\/\/[^\s"']+

The s? makes the “s” optional. Then it grabs everything up to the next space or quote. Good enough for pulling links out of text, though it may include trailing punctuation.

7. Trim whitespace from both ends

^\s+|\s+$

Use it with the global flag and replace the matches with nothing. It removes leading and trailing whitespace on each string.

8. Collapse repeated spaces

\s{2,}

Replace with a single space to tidy messy text. For related cleanup, the Remove Duplicate Lines tool and the Case Converter handle common jobs without writing any pattern.

9. A US-style phone number

\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}

Handles “(555) 123-4567”, “555.123.4567” and “5551234567”. Phone formats differ across countries, so decide which formats your data really uses.

10. Capture and reorder a date

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

Each pair of brackets captures a piece. In most replace boxes you can write $3/$2/$1 to turn 2026-11-05 into 05/11/2026. Some tools use \3/\2/\1 instead.

11. Anything inside HTML tags (lazily)

<.+?>

Matches each tag separately. See the greedy versus lazy section below for why the question mark matters.

12. Password rule check with lookaheads

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$

Each (?=...) is a lookahead, a check that does not consume characters. This one requires a digit, a lowercase letter and an uppercase letter, and at least eight characters in total. Be aware that forced composition rules are no longer recommended; our guide to strong passwords explains why length matters more.

13. Spot duplicated words

\b(\w+)\s+\1\b

The \1 is a backreference. It matches whatever group 1 captured, so this finds “the the” in “this is the the problem”. A favourite for proofreading.

14. A rough IPv4 address

\b(?:\d{1,3}\.){3}\d{1,3}\b

Four groups of one to three digits separated by dots. It will happily accept 999.999.999.999, so validate each number from 0 to 255 in code if it matters.

15. A URL slug

^[a-z0-9]+(?:-[a-z0-9]+)*$

Lowercase letters and digits, separated by single hyphens, with no leading or trailing hyphen. To create such a slug from a title, use the Text to Slug Converter.

Groups, backreferences and replacing

Capturing groups do two jobs. They let you pull out parts of a match, and they let you rebuild the text in a replacement. In JavaScript you can name a group to make the code easier to read:

const m = "2026-11-05".match(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/);
m.groups.y  // "2026"
m.groups.m  // "11"

A few habits keep patterns manageable:

  • Use (?: ) when you need grouping only, not capturing. It is slightly faster and keeps group numbers tidy.
  • Name groups when a pattern has more than two or three.
  • Add comments in code explaining what the pattern does, since you will not remember in six months.

Greedy vs lazy matching

By default, quantifiers are greedy: they grab as much text as they can while still letting the overall pattern succeed. That is a common source of surprise.

Text: <b>bold</b> and <i>italic</i> Greedy <.+> <b>bold</b> and <i>italic</i> Lazy <.+?> <b>bold</b> and <i>italic</i>
Figure 2. The greedy pattern swallows everything from the first < to the last > as one match. The lazy version stops at the first > and yields four separate tags.

Adding a ? after a quantifier makes it lazy: *?, +?, {2,5}?. An even more precise alternative is to say what the match cannot contain, such as <[^>]+>, which means “an opening bracket, then one or more characters that are not a closing bracket, then a closing bracket”. It is often faster and clearer than a lazy quantifier.

Flags

Flags change how the whole pattern behaves. In JavaScript they come after the closing slash, as in /cat/gi.

FlagEffect
gGlobal: find all matches, not just the first
iIgnore case: “Cat”, “CAT” and “cat” all match
mMultiline: ^ and $ match at each line, not just the text ends
sDot-all: . also matches newlines
uUnicode: treats characters beyond the basic plane correctly

Other languages spell these differently, and some engines have extra flags, so check the documentation of the language you use.

Performance and catastrophic backtracking

Most patterns run instantly. A few pathological ones can take exponential time. The classic example is a nested quantifier such as (a+)+$ tested against a long string of letter “a” followed by a “b”. When the match fails at the end, the engine tries every possible way of splitting the run of a’s among the nested groups, and the number of ways explodes.

This is more than a curiosity. When a service runs a vulnerable pattern on user input, a crafted string can lock up a CPU. It is known as a regular expression denial of service, or ReDoS. To stay safe:

  • Avoid nesting quantifiers around the same characters, as in (x+)* or (.*)*.
  • Prefer specific character classes to .* when you can.
  • Anchor patterns with ^ and $ when validating.
  • Limit the length of input before you run a pattern against it.
  • Use a regex engine that guarantees linear time if you must accept untrusted patterns.

When not to use a regex

Regex is a hammer, and not everything is a nail. Reach for a proper tool instead when:

  • Parsing HTML or XML. Nested, optional and malformed structure defeats simple patterns. Use a parser, or a purpose-built extractor like the HTML Link Extractor.
  • Working with JSON. Parse it, do not match it. The JSON Formatter and JSON Validator will show you the real structure and point at errors.
  • Validating complicated standards, such as full email, dates in real calendars, or URLs. Use the platform’s own functions.
  • Comparing two versions of a text. A diff checker is the right tool.

Similarly, scheduling strings such as 0 9 * * 1-5 look a bit like regex but follow their own rules. The Cron Expression Explainer translates them into plain English, and the Unix Timestamp Converter helps when logs use epoch times.

A workflow for writing patterns that work

  1. Collect real sample text, including awkward cases and ones that should not match.
  2. Write the simplest pattern that matches the obvious cases.
  3. Run it in a tester and watch what it matches that you did not expect.
  4. Tighten it with anchors, boundaries and specific classes.
  5. Check the failure cases, including empty input and very long input.
  6. Save the sample strings as tests alongside the code.

Frequently asked questions

What is the difference between regex flavours?

Engines such as JavaScript, Python, PCRE and Java share the core syntax but differ in details like lookbehind support, named groups and flags. If a pattern works in one place and not another, a flavour difference is the first thing to check.

How do I match a literal dot or bracket?

Escape it with a backslash: \. for a dot, \( for a bracket. Inside a character class, most special characters lose their meaning, so [.] also matches a dot.

Why does my pattern match too much?

Usually greediness. Try a lazy quantifier or, better, a negated class like [^"]* that cannot run past the character you want to stop at.

Is it worth learning regex?

Yes. Even a handful of patterns will speed up editing, searching logs and cleaning data, and they work in almost every tool.

Related guides and tools

References

  1. MDN Web Docs, “Regular expressions” guide for JavaScript. developer.mozilla.org
  2. Regular-Expressions.info, tutorials and engine comparisons. regular-expressions.info
  3. Wikipedia, “Regular expression”: history, syntax and implementations. en.wikipedia.org/wiki/Regular_expression
  4. OWASP, “Regular expression Denial of Service (ReDoS)”. owasp.org

Patterns here are teaching examples. Test them against your own data and treat validation patterns as a first filter, not a guarantee.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top