Regex anchors and multiline mode
A pattern that matches the text you want in the middle of a string can still match in places you did not intend. Anchors fix that by tying a match to a position rather than a character, and the multiline flag quietly changes what those positions mean.
Anchors match positions, not characters
^ and $ do not consume any character. They assert where in the string the engine currently is:
^asserts the start of the string.$asserts the end of the string.
So ^abc$ matches the string abc and nothing else, because the match must begin at the start and finish at the end. By contrast abc with no anchors matches anywhere the three letters appear, including inside xabcy.
This is why anchors are the tool for whole string validation. ^\d{5}$ accepts a five digit zip code but rejects 12345x, because the x sits between the final digit and the end position.
The word boundary
\b is a third anchor, and it is the one people reach for most once they understand it. It asserts a position between a word character (\w, meaning letters, digits, and underscore) and a non word character, or at the start or end of the string next to a word character.
\bcat\b
This matches cat in the cat sat but not in category or scatter, because inside those words there is no boundary on both sides. Use \b whenever you want a standalone word rather than a substring. Its opposite, \B, asserts a position that is not a boundary.
What the m flag changes
Without any flags, a string with newlines in it is still one string, so ^ and $ only match at its very start and very end. The multiline flag, m, redefines them:
- With
m,^matches at the start of the string and immediately after every newline. - With
m,$matches at the end of the string and immediately before every newline.
Consider this input:
error: disk full
ok: ready
The pattern ^error: with no flag matches once, only if the string starts with error:. The same pattern with the m flag matches at the start of any line that begins with error:. That is the behavior you want when processing logs or configuration line by line.
One common confusion: the m flag does not make . match newlines. That is a separate flag, s, called dotall.
Trying it live
Position based matching is easy to get wrong in your head and easy to confirm by watching it. Paste a sample into the Regex Tester, toggle the m flag, and see the highlighted matches move from one per string to one per line. Everything runs in your browser, so the input never leaves your device.
The takeaway: anchors pin a match to a place, \b isolates whole words, and the m flag switches ^ and $ from whole string to per line. Pick the mode that matches how your data is laid out, and verify it on real sample text.