The Shack Developer Tips Regex for Beginners: Writing Your First Patterns

Regex for Beginners: Writing Your First Patterns (With a Live Tester)

Back to All Posts

Regular expressions — regex for short — are one of those things developers avoid for years, then can't live without once they learn them. They look intimidating at first glance (/^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$/ — what?), but they're built from just a handful of simple concepts that stack together logically.

This guide walks through every building block from scratch. And because reading about regex without being able to test it is frustrating, you can try every example in the DevToolShack Regex Tester — live, in your browser, no sign-up needed.

What Is a Regular Expression?

A regular expression is a pattern that describes a set of strings. You use that pattern to search, match, extract, or replace text. Nearly every programming language supports regex: JavaScript, Python, PHP, Ruby, Java, Go — they all have built-in regex engines.

In most languages, a regex pattern is written between forward slashes: /pattern/flags. The flags modify how the match works — more on those below.

The Simplest Pattern: Literal Text

The simplest regex is just the text you're looking for:

hello

This matches the exact string hello anywhere in the input. Case-sensitive by default — it won't match Hello or HELLO.

Try it now: Open the Regex Tester, type hello as your pattern, and paste in some text. Watch it highlight every match in real time as you type.

Flags: Modifying How Matches Work

Flags go after the closing slash and change the matching behavior:

FlagNameWhat it does
iCase-insensitiveMatches Hello, HELLO, hello equally
gGlobalFinds all matches, not just the first one
mMultilineMakes ^ and $ match start/end of each line
sDotallMakes . match newline characters too

So /hello/gi finds every occurrence of "hello" regardless of capitalisation.

The Dot: Match Any Character

A dot . matches any single character except a newline:

h.t

This matches hat, hit, hot, h3t, h t — any character in the middle position. To match a literal dot, escape it: \.

Character Classes: Match One of These

Square brackets define a character class — match any one character from the set:

[aeiou]

Matches any single vowel. You can also use ranges:

[a-z]     # any lowercase letter
[A-Z]     # any uppercase letter
[0-9]     # any digit
[a-zA-Z0-9]  # any letter or digit

A caret ^ at the start of a character class negates it:

[^aeiou]  # any character that is NOT a vowel

Shorthand Character Classes

These are so common they have shortcuts:

ShorthandEquivalentMatches
\d[0-9]Any digit
\D[^0-9]Any non-digit
\w[a-zA-Z0-9_]Any word character
\W[^a-zA-Z0-9_]Any non-word character
\s[ \t\r\n]Any whitespace
\S[^ \t\r\n]Any non-whitespace

Quantifiers: How Many Times?

Quantifiers go after a character or group and say how many times it should match:

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

So \d+ matches one or more digits, and \d{3}-\d{4} matches a US local phone number format like 555-1234.

Anchors: Position in the String

Anchors don't match characters — they match positions:

  • ^ — matches the start of the string (or line in multiline mode)
  • $ — matches the end of the string (or line)
  • \b — matches a word boundary
^\d{5}$

This matches a string that is exactly 5 digits — like a US ZIP code. Without the anchors, \d{5} would also match the digits inside abc12345xyz.

Groups and Alternation

Parentheses create a group — they let you apply quantifiers to multiple characters, or capture part of the match:

(cat|dog)s?

This matches cat, cats, dog, or dogs. The pipe | means "or", and the s? makes the "s" optional.

Real-World Patterns to Steal

Here are some battle-tested patterns you can use immediately — paste them into the Regex Tester to see them in action:

# Email address (basic)
^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$

# US phone number (flexible)
\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}

# URL
https?://[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?

# IPv4 address
\b(\d{1,3}\.){3}\d{1,3}\b

# Date (YYYY-MM-DD)
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])

# Hex color code
#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})
Email validation caveat: No regex perfectly validates all valid email addresses — the full spec is surprisingly complex. Use regex for basic format checking, but always send a confirmation email to truly verify an address.

Greedy vs Lazy Matching

By default, quantifiers are greedy — they match as much as possible. Add a ? after the quantifier to make it lazy — match as little as possible:

# Input: <b>bold</b> and <i>italic</i>

<.+>    # Greedy: matches the whole thing from first < to last >
<.+?>   # Lazy: matches <b>, then </b>, then <i>, then </i> separately

This trips up a lot of beginners — if your pattern is matching too much, try adding ? after your quantifier.

Using Regex in JavaScript

const email = "ada@example.com";
const pattern = /^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$/;

// Test if it matches
pattern.test(email);  // true

// Extract all matches from a string
const text = "Call 555-1234 or 555-5678";
const phones = text.match(/\d{3}-\d{4}/g);  // ["555-1234", "555-5678"]

// Replace matches
const cleaned = text.replace(/\d{3}-\d{4}/g, "[REDACTED]");
// "Call [REDACTED] or [REDACTED]"
Keep practicing: The Regex Tester shows match highlights, group captures, and match details in real time — it's the fastest way to build pattern intuition. Write a pattern, break it, fix it, repeat.