Regex character "$" doesn't mean "end-of-string"
Core dispute: What $ means
- Thread centers on the fact that in many engines
$in non‑multiline mode matches either end-of-string or just before a trailing\n, not strictly “end-of-string.” - Some engines (JS, Go, Rust, RE2-style) make
$equivalent to “end of string” when multiline is off. - Others (Python, Java, C#, PHP, Perl, PCRE, etc.) treat
$more like “end of line,” with a special case for a single trailing newline. - Several commenters find the Python/Perl-style behavior surprising and “whacky,” especially examples like
cat$not matchingcat\n\n.
Line vs string semantics
- Big subthread argues whether
$is conceptually “end of line” or “end of string.” - One side insists the historical, line-based view (from editors,
ed/sed/grep) justifies$treating a trailing newline specially. - The other side counters that most APIs take arbitrary strings, not lines, so users reasonably expect
$to mean “end of string.” - There is debate over POSIX definitions of “line,” “incomplete line,” and how newline as terminator vs separator should affect
$.
Regex dialects and (lack of) standardization
- Many note there is no single regex standard; there are multiple families:
- POSIX BRE/ERE, with different anchor semantics.
- Perl/PCRE and descendants (PHP, many languages, PCRE2).
- RE2-style, used by Go and Rust’s regex crate, which deliberately avoid some Perl quirks.
- JavaScript’s ECMA regex, with its own gaps and features.
- C++
<regex>, ECMA-262, POSIX, and a recent RFC (I-Regexp) are mentioned as formal specs, but they coexist rather than unify behavior.
Security and correctness implications
$matching before a trailing newline has led to real bugs, e.g., in Ruby input validation and ExifTool/GitLab vulnerabilities, where attackers smuggle payloads after a newline.- Recommendation in several comments: when you truly mean “whole string,” use
\A...\Zor\zwhere available, not^...$.
Tooling, usage patterns, and ergonomics
- Many advise always checking the specific engine’s docs and testing regexes explicitly.
- Some prefer line-oriented tools (grep/sed/awk, editors like Vim) and think in terms of lines; others primarily work with in-memory strings and expect string semantics.
- Broader frustration appears around regex flavor fragmentation, escaping rules, and inconsistent support for character classes and anchors.