Regular Expressions › Anchors: Position Matching
Language AI HandbookAll chapters Regular Expressions › Anchors: Position MatchingOne section · Sections in this chapter6 / 21 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Anchors match positions in the string rather than characters. Unlike metacharacters that consume text, anchors assert that the current position in the string meets certain criteria. This makes them essential for matching patterns at specific locations, such as the beginning of a line or at word boundaries.
Think of anchors as conditions that must be satisfied at a specific point in the string, not as characters to match. The anchor ^ says "the engine must be at the start of the string right now." The anchor \b says "the engine must be at a word boundary right now." If the condition is not met at the current position, the match fails at that position and the engine tries the next one. Because anchors consume no characters, you can stack them: ^$ matches an empty line (must simultaneously be at the start and end of a line). This zero-width property is what distinguishes anchors from all other regex elements.
The word boundary anchor \b deserves special attention for NLP work. It matches the invisible boundary between a word character and a non-word character. At the beginning of the string, \b matches if the first character is a word character. At the end of the string, \b matches if the last character is a word character. In the middle of a string, \b matches at every transition between \w and \W. This makes \bword\b the correct way to match whole words, because it rejects partial matches like "password" when you only want "word". Without word boundaries, searching for common words like "the" or "at" produces enormous numbers of false positives inside longer words.
text = "Hello World\nHello Python"
# ^ matches start of string (or line with MULTILINE)
start_matches = re.findall(r"^Hello", text, re.MULTILINE)
# $ matches end of string (or line with MULTILINE)
end_matches = re.findall(r"World$|Python$", text, re.MULTILINE)
# \b matches word boundary
word_boundary = re.findall(r"\bcat\b", "The cat sat on the catalog")
# \B matches non-word boundary
non_boundary = re.findall(r"\Bcat\B", "The cat sat on the catalog")Text: 'Hello World\nHello Python' ^ (start of line with MULTILINE): Pattern: ^Hello Matches: ['Hello', 'Hello'] $ (end of line with MULTILINE): Pattern: World$|Python$ Matches: ['World', 'Python'] \b (word boundary): Text: 'The cat sat on the catalog' Pattern: \bcat\b Matches: ['cat'] \B (non-word boundary): Pattern: \Bcat\B Matches: []
Word boundaries are essential for matching whole words. The \b anchor matches the position between a word character and a non-word character. In "catalog", there's no word boundary before or after "cat", so \bcat\b doesn't match it.
In practice, you should default to using word boundaries whenever you search for words in natural text. The cost is negligible and the benefit is avoiding spurious matches. A search for \brun\b correctly identifies the verb in "I run every day" without matching "runtime", "running", "outrun", or "rundown". This is particularly important in NLP pipelines where false positives silently corrupt downstream analysis.