Anchors and word boundaries

Regular expressions · Essentials · 8 min

Without anchors, a validation pattern accepts any string that merely contains a valid part.

Anchors match a position, not a character, so they consume no text:

  • ^ start of the string (or of each line in multiline mode).
  • $ end of the string (or of each line in multiline mode). In Python and PCRE $ also matches just before a final newline; in JavaScript it doesn't.
  • \b a word boundary: between a word character (\w) and a non-word character or the string edge. \bcat\b finds cat but not concatenate. \B is the opposite.
  • \A and \z (Python: \A and \Z) always mean the very start and very end of the string, regardless of flags.

Anchors are essential for validation. \d{5} finds five digits inside "abc123456", so it would accept that string as a ZIP code; ^\d{5}$ requires the whole string to be five digits. In Python re.fullmatch(r"\d{5}", s) does the same without anchors and avoids the trailing-newline subtlety of $.

Word boundaries depend on what counts as \w, so \b treats - and ' as boundaries: \bcan\b matches inside can't.

Example

import re

print(re.findall(r"cat", "cat concatenate"))       # ['cat', 'cat']
print(re.findall(r"\bcat\b", "cat concatenate"))   # ['cat']

zip_re = re.compile(r"^\d{5}$")
print(bool(re.search(r"\d{5}", "abc123456")))      # True  (contains five digits)
print(bool(zip_re.search("abc123456")))           # False
print(bool(zip_re.search("12345")))               # True
print(bool(zip_re.search("12345\n")))             # True!  $ allows a final newline
print(bool(re.fullmatch(r"\d{5}", "12345\n")))    # False

lines = "error: a\nok\nerror: b"
print(re.findall(r"^error: (\w)", lines, re.MULTILINE))   # ['a', 'b']

Remember

  • ^ and $ anchor to the start and end; \b to word edges
  • Validation patterns must be anchored (or use fullmatch)
  • In Python and PCRE, $ also matches before a final newline

Watch out for

  • Validating input with an unanchored pattern, which accepts anything that contains a valid substring.

Check yourself

  1. Why does re.search(r'\d{3}', 'abcd1234') succeed?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Assertions