iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Anchors ^ $ \b

Anchors match positions, not characters. ^ = start of string / line, \$ = end of string / line, \b = word boundary, \B = not-a-word-boundary. The shape of every disciplined regex.

All the anchors with examples

EXAMPLE
// 1) ^ — start of string
/^Hello/.test('Hello world')        // true
/^Hello/.test('say Hello')          // false

// 2) $ — end of string
/world$/.test('Hello world')        // true
/world$/.test('world peace')        // false

// 3) Combine — exact match
const isInteger = /^-?\d+$/;
isInteger.test('42')                // true
isInteger.test('42abc')             // false

// 4) Multiline flag — ^ and $ match every LINE, not just start/end of string
const lines = 'line one\nline two\nERROR\nline four';
lines.match(/^ERROR$/m)?.[0]        // 'ERROR'
lines.match(/^line.*$/gm)            // every line starting with 'line'

// 5) \b — word boundary (between \w and \W or start/end)
/\bcat\b/.test('the cat sat')       // true
/\bcat\b/.test('caterpillar')       // false
/\bcat\b/.test('a-cat-here')        // true (- is not a word char)

// Useful pattern — match a WHOLE word
/\bclass\b/g                         // matches 'class' but not 'classroom'

// 6) \B — NOT a word boundary
/\Bcat\B/.test('caterpillar')       // false (start of cat is a boundary)
/\Bcat\B/.test('scatter')           // true (cat is in the middle)

// 7) \A and \z — start/end of STRING in PCRE / Python / Ruby (NOT JS)
# Python
# import re
# re.search(r'\Astart', 'start of string')      # like ^ but ignores multiline
# re.search(r'end\z', 'end of string')          # like $ but ignores multiline

// 8) (?=) — lookahead (zero-width assertion, NOT an anchor but acts like one)
/foo(?=bar)/.test('foobar')         // true — 'foo' followed by 'bar'
/foo(?!bar)/.test('foobaz')         // true — 'foo' NOT followed by 'bar'
/(?<=USD)\d+/.exec('USD42')?.[0]    // '42' (lookbehind, modern JS)

// 9) Real recipes

// 9a) Trim whitespace
'   hello world   '.replace(/^\s+|\s+$/g, '')

// 9b) Match leading hash tag
'/users/42/posts'.match(/^\/users\/(\d+)/)?.[1]

// 9c) Match line not starting with #
config.split('\n').filter(l => /^[^#].+/.test(l))

// 9d) Standalone TODO comments (whole word)
'fix this todo'.match(/\bTODO\b/gi)

// 9e) Email-like (intentionally rough — you should NOT validate email with regex; use a library)
const rough = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

// 10) Pitfalls
//   • Forgetting ^ + $ when validating → '42abc' passes a number check
//   • Using \b in code that allows -, _, or unicode — \b is ASCII word chars only
//   • Multiline mode changes ^/$ meaning — be intentional with the m flag
//   • Anchors don't consume characters — they're zero-width

// 11) Regex flags cheat sheet (JS)
//   g — global (find all)
//   i — case-insensitive
//   m — multiline (^/$ per line)
//   s — dotall (. matches \n)
//   u — unicode
//   y — sticky (matches from lastIndex only)
//   v — modern unicode (set ops + named props)

// 12) Tools
//   • regex101.com — visualise + benchmark
//   • regexr.com — quick reference
//   • RE2 (in ripgrep, Go) — linear time, no catastrophic backtracking

Why it matters

Always wrap validation regex in ^...\$. Without them, /[0-9]+/ matches “42” inside “Order 42abc shipped” — the most-shipped silent bug class in regex code.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
^foo        // start of string (or line with m flag)
bar$        // end of string
\bword\b   // word boundary
\Bword     // NOT at a word boundary
Try it Yourself »

Exercise

Anchor for end of string.

/foo /

Discussion

Loading…