Code of the Day
BeginnerCore syntax

Anchors

Pin patterns to the start or end of a string, or to a word boundary, using ^, $, \b, and \B.

Regular ExpressionsBeginner8 min read
Recommended first
By the end of this lesson you will be able to:
  • Use ^ and $ to require a pattern at the start or end of a string
  • Use \b to match only at a word boundary
  • Distinguish string anchors from line anchors under the multiline flag

By default a regex pattern can match anywhere inside a string. Anchors change that: they assert a position in the string rather than consuming characters. An anchor matches a location — the start, the end, or a boundary between character types — not a character.

^ — start of string

^ asserts that the following pattern must begin at the very start of the string:

/^hello/.test("hello world");   // true  — starts with "hello"
/^hello/.test("say hello");     // false — "hello" is not at the start
/^hello/.test("Hello world");   // false — case-sensitive by default

Without ^, the same pattern /hello/ would match in all three strings (the first two at least). The anchor makes it strict.

$ — end of string

$ asserts that the preceding pattern ends at the very end of the string:

/world$/.test("hello world");   // true  — ends with "world"
/world$/.test("worldwide");     // false — "world" is not at the end
/.csv$/.test("report.csv");     // true
/.csv$/.test("report.csv.bak"); // false

Combining ^ and $

Together, ^ and $ require the pattern to span the entire string:

/^\d{5}$/.test("12345");      // true  — exactly 5 digits
/^\d{5}$/.test("1234");       // false — too short
/^\d{5}$/.test("123456");     // false — too long
/^\d{5}$/.test("1234x");      // false — non-digit at the end

This is the standard form for input validation — you do not want a ZIP code validator that accepts "abc 12345 def" just because the substring 12345 appears somewhere in it.

\b — word boundary

\b asserts a position between a word character (\w) and a non-word character (\W), or between a word character and the start/end of the string:

/\bcat\b/.test("the cat sat");    // true  — "cat" surrounded by spaces
/\bcat\b/.test("concatenate");    // false — "cat" is inside a word
/\bcat\b/.test("cats");           // false — "s" is still a word char
/\bcat/.test("cats");             // true  — boundary before, no boundary after

Word boundaries are invaluable for whole-word matching. Without \b, /error/ matches inside "erroring", "errors", and "TypeError". With /\berror\b/ you match only the standalone word.

\b does not consume any characters. It is a zero-width assertion — it matches a position, not content. Two patterns with the same characters but different anchor choices can produce very different results.

\B — non-word boundary

\B is the opposite: it matches at a position that is not a word boundary — meaning both adjacent characters are word characters, or both are non-word characters:

/\Bcat\B/.test("concatenate");  // true  — "cat" is embedded
/\Bcat\B/.test("the cat sat");  // false — "cat" has boundary on both sides

\B is less common but useful when you want to find a string only when it appears inside a larger word.

^ and $ under the multiline flag

By default ^ and $ refer to the start and end of the entire string. When you add the m (multiline) flag they refer to the start and end of each line:

const log = "ERROR: disk full\nWARN: retry\nERROR: timeout";

// Without m — anchors to the whole string
log.match(/^ERROR/);    // ["ERROR"] — only the very first line
log.match(/^ERROR/g);   // ["ERROR"] — still only first

// With m — anchors to each line
log.match(/^ERROR/gm);  // ["ERROR", "ERROR"] — both ERROR lines

The m flag changes only ^ and $. It does not make . match newlines — for that you need the s (dotall) flag, covered in the flags lesson.

\A and \Z

Some engines (Python, Ruby) provide \A (start of string, always — not affected by multiline) and \Z (end of string, always). JavaScript does not support these; ^ and $ without the m flag are the equivalent.

In Python:

import re
re.match(r"\A\d{5}\Z", "12345")   # match
re.match(r"\A\d{5}\Z", "12345\n") # no match — \Z requires end-of-string

Putting it together

JavaScript — editable, runs in your browser

Anchor quick reference

AnchorAsserts
^Start of string (or line with m flag)
$End of string (or line with m flag)
\bPosition between word char and non-word char
\BPosition between two word chars or two non-word chars
\AStart of string (Python/Ruby; always, not affected by multiline)
\ZEnd of string (Python/Ruby; always, not affected by multiline)

Where to go next

You have now covered the core building blocks: literals, metacharacters, character classes, quantifiers, and anchors. The Core syntax lab lets you apply all of them to realistic problems — ZIP codes, dates, phone numbers — before moving on to groups and flags.

Finished reading? Mark it complete to track your progress.

On this page