The $ quantifier is an end anchor. It matches a position—not a character—at the end of the input string. Combine it with literal text or groups to require a suffix: file extensions, domain endings, punctuation, or keywords that must appear last.
01
$ anchor
End of string
02
Zero-width
No characters
03
$ + m
Each line end
04
Suffix
.pdf, ing
05
Not replace
Pattern vs $1
06
Pair ^
Full-line match
Fundamentals
Introduction
Many validation tasks care about where text appears, not just what it contains. Does a filename end in .pdf? Does a sentence end with a question mark? Does a log line finish with OK? The $ anchor answers those questions by insisting the match reaches the end of the string.
Without $, the pattern /world/ matches "hello world" anywhere the letters appear. Adding $ turns it into /world$/, which matches only when world is the final characters—a much stricter and often more useful rule.
Concept
Understanding the $ End Anchor
Place $ at the end of a pattern (or before a trailing flag like /i). It asserts that the current match position is at the end of the input. With the m multiline flag, it also matches immediately before each newline, so each line can have its own “end.”
JavaScript
const ok = "hello world";
const no = "world hello";
/world$/.test(ok); // true — ends with "world"
/world$/.test(no); // false — "world" is not at the end
/end$/m.test("line one end\nline two end"); // true — both lines end with "end"
$ is zero-width: it checks a boundary without consuming characters. That is why /world$/ on "hello world" matches the substring "world" at the string tail.
💡
Beginner Tip
Do not confuse $ in a pattern with $1 in a replacement string. In str.replace(/(\w+)$/, "[$1]"), the first $ is an end anchor; the $1 in the replacement refers to the captured word.
Usage
How to Use the $ Anchor
Append text or groups before $ to require a suffix, or pair ^ and $ to match an entire line or string:
JavaScript
/\.pdf$/i.test("report.PDF"); // true — extension at end
/\d+$/.test("item42"); // true — trailing digits
/^.+$/m.test("a\nb\nc"); // true — each line non-empty
"photo.jpg".replace(/\.(jpg|png)$/i, ".webp"); // "photo.webp"
Use test() for yes/no checks, match() to extract the suffix, and replace() to rewrite endings. Add m when working with multi-line strings.
Foundation
📝 Syntax
JavaScript
/suffix$/ // ends with literal "suffix"
/\.(jpg|png)$/i // image extension at end
/\d+$/ // one or more digits at end
/pattern$/m // end of each line (with m)
/^start.+end$/ // whole string from start to end
new RegExp("end$", "m") // constructor form
Common patterns
/\.(pdf|docx?)$/i — document file extensions.
/[!?.]$/ — sentence ends with punctuation.
/^\s*$/m — find blank lines (with m).
/ing$/i — words ending in ing.
/^.+$/gm — capture every non-empty line.
Cheat Sheet
⚡ Quick Reference
Goal
Pattern / API
Ends with text
/text$/
Ends with extension
/\.ext$/i
Ends with digits
/\d+$/
End of each line
/pattern$/m
Full string match
/^pattern$/
Capture suffix group
/(.+)$/.exec(str)[1]
Compare
📋 $ in Patterns vs Replacements
Same symbol, different jobs depending on where it appears.
Pattern
/world$/
End anchor — must finish with world
Replacement
"[$1]"
$1 inserts capture group 1
No $
/world/
Matches anywhere in string
With $
/world$/
Only when world is last
Hands-On
Examples Gallery
Open DevTools Console (F12) or use Try-it links. Examples cover basic suffix matching, multiline line ends, file extensions, trailing digits, and full-line validation with ^ and $.
$ forces the engine to reach the string tail. "world peace" contains world but not at the end, so the test fails.
📈 Practical Patterns
Line endings, extensions, and validation.
Example 2 — End of Each Line with $ and m
Find lines that end with end in multi-line text.
JavaScript
const text = "line one end\nline two end\nno match";
console.log(/end$/.test(text)); // false — whole string ends with "match"
console.log(/end$/m.test(text)); // true — lines 1 and 2 end with "end"
console.log(text.match(/end$/gm)); // ["end", "end"]
Without m, $ only checks the final character of the entire string. With m, each newline creates an additional end position. Add g to collect every matching line ending.
\d+ greedily matches digits; $ anchors them to the tail. The captured group returns just the number portion.
Example 5 — Full-Line Match with ^ and $
Ensure an entire string matches a pattern from start to finish.
JavaScript
const hexColor = /^#[0-9a-f]{6}$/i;
console.log(hexColor.test("#ff00aa")); // true
console.log(hexColor.test("#ff00")); // false — too short
console.log(hexColor.test("color #ff00aa")); // false — extra text
In replacement strings, use $$ for a literal dollar sign.
Compatibility
Browser & Runtime Support
The $ end anchor is part of core JavaScript regular expression syntax.
✓ Baseline · ES3+
RegExp $ anchor
Supported in every browser and Node.js version. Combine with m for line-by-line end matching.
99%Universal syntax
Google ChromeSupported · Desktop & Mobile
Full support
Mozilla FirefoxSupported · Desktop & Mobile
Full support
Apple SafariSupported · macOS & iOS
Full support
Microsoft EdgeSupported · Chromium
Full support
Internet ExplorerNo native support · Use a polyfill
Polyfill
OperaSupported · Modern versions
Full support
Samsung InternetSupported · Android
Full support
BunSupported · JavaScript runtime
Supported
DenoSupported · JavaScript runtime
Supported
Node.jsSupported · Server runtime
Supported
Android WebViewSupported · Modern WebView
Full support
$Excellent
Bottom line: Safe everywhere. Use $ when a pattern must finish at the end of a string or line.
Wrap Up
Conclusion
The $ quantifier is the end anchor: it ensures your pattern finishes where you expect—at the tail of a string, a filename, or (with m) each line of multi-line text. It is zero-width, precise, and essential for suffix checks and strict validation.
Remember the difference between $ in patterns and $1 in replacements, add m for multi-line input, and pair ^ with $ when the entire value must match. Next, explore ?! negative lookahead.
Use $ when suffix position matters (extensions, endings)
Add m for multi-line strings that need per-line ends
Combine ^ and $ for strict full-value validation
Escape literal dots in extensions: \.pdf$
Test with real input including trailing spaces and \r\n
❌ Don’t
Confuse pattern $ with replacement $1
Forget m when matching line endings in logs or configs
Assume $ consumes the last character
Use /pattern$/ alone when the whole string must match
Mix up $ end anchor with \b word boundary
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about the RegExp $ anchor
Match suffixes and end-of-string patterns with confidence.
5
Core concepts
🔢01
$ anchor
End position.
Syntax
📈02
Zero-width
No chars eaten.
Concept
📄03
$ + m
Line ends.
Multiline
🔒04
^ $
Full match.
Validate
🚫05
Not $1
Replace only.
Pitfall
❓ Frequently Asked Questions
In a pattern, $ is a zero-width end anchor. It matches a position at the end of the input string, or—when the m (multiline) flag is set—immediately before each newline character. It does not consume any characters.
No. In a pattern, $ asserts end of string or line. In a replacement string passed to replace() or replaceAll(), $1, $2, etc. refer to capture groups, and $$ inserts a literal dollar sign. The meaning depends on context.
Use $ with m when your text contains newlines and you want to match the end of each line—not only the very last character of the entire string. Example: /end$/m matches end at the close of every line.
By default, $ matches the end of the string. With m, it also matches the position before an internal newline. A final trailing \n may still affect whether text before it is considered at line end—test with your actual input.
$ matches end of string or line (with m). \b matches a word boundary between word and non-word characters. /ing\b/ finds ing as a word suffix; /ing$/ requires ing to be at the string or line end.
The $ anchor is core JavaScript regex syntax since ES3. It works in every browser and Node.js version. Multiline behavior with m is equally universal.
Did you know?
JavaScript borrowed the $ end anchor from Perl-style regular expressions decades ago. The same symbol does double duty in replace() replacement strings—which is why reading regex documentation carefully (pattern vs replacement context) saves hours of debugging.