Lesson 2 of 6

Basic Patterns

Every regex, no matter how intimidating it looks, is built from a small handful of building blocks stacked together. Before the special symbols, there's the simplest case of all: a letter just means that letter. Once that clicks, the two most common special symbols — the dot and the anchors — are easy additions on top.

💡 The Bottom Line

Most characters in a regex match themselves literally. The dot . matches any single character. The anchors ^ and $ pin a match to the start and end of the string. Together, these let you tell the difference between "this text contains a match somewhere" and "this whole string matches, start to finish."

Literal characters

The regex cat matches the three characters "c", "a", "t" in that exact order, wherever they appear:

/cat/.test("concatenate")  // true  — "cat" appears inside "concatenate"
/cat/.test("category")     // true  — "cat" appears at the start
/cat/.test("dog")          // false — no "cat" anywhere

Notice that a match doesn't require the whole string to be exactly "cat" — by default, a regex just needs to find its pattern somewhere in the string, unless you tell it otherwise.

The dot: match any single character

A dot . matches any one character (except a newline, by default) — a kind of wildcard placeholder:

/c.t/.test("cat")   // true  — "a" fills the dot
/c.t/.test("cot")   // true  — "o" fills the dot
/c.t/.test("ct")    // false — the dot needs exactly one character present
/c.t/.test("caat")  // false — two characters between c and t, dot only covers one

⚠️ Watch Out

A literal dot character (like the one in a decimal number or a filename extension) needs to be escaped as \. — otherwise it's the "match anything" wildcard, not a literal period. Forgetting this is one of the most common regex mistakes; you'll see it again in Lesson 6.

Anchors: pinning to start and end

^ means "the match must start here, at the beginning of the string." $ means "the match must end here, at the end of the string." Using both together forces the entire string to match the pattern, not just some substring of it.

const zip = /^\d{5}$/;

zip.test("90210")     // true  — exactly 5 digits, nothing before or after
zip.test("90210 ")    // false — trailing space means it doesn't end right after the digits
zip.test("A90210")    // false — doesn't start right at the digits
zip.test("902100000") // false — more than 5 digits, so $ fails right after the 5th

📋 "Contains a match" vs. "the whole string matches"

  • No anchors (e.g. /cat/) — true if the pattern appears anywhere in the string, even as part of a longer word.
  • Anchored both ends (e.g. /^cat$/) — true only if the entire string is exactly that pattern, nothing more, nothing less.
  • Validation (is this whole input a valid zip code?) almost always wants both anchors. Searching (does this paragraph mention "cat" anywhere?) usually wants no anchors at all.

🙋 There Are No Dumb Questions

Q: If I forget the anchors on a validation regex, what actually goes wrong?
A: Without anchors, /\d{5}/ would happily match a substring inside a longer, invalid string — "90210-extra-junk" would pass, because it contains five digits somewhere, even though the whole string clearly isn't a valid zip code. Anchors are what turn a "search" pattern into a "validate the whole thing" pattern.

🔧 Try It Yourself

In a console, compare /^\d{5}$/.test("90210x") to /\d{5}/.test("90210x"). One returns false, the other true — work out why before running it, then confirm.

✅ Quick Check

What does the pattern /^abc$/ require that /abc/ does not?


Next up: character classes and quantifiers — how to match "any digit" or "any letter" and say how many times something should repeat.

← Back to
Next →