Escaping and literal text¶
One line: Fourteen characters have a meaning in a pattern and need a backslash to be themselves — the same fourteen in every engine here — and the rest of the story is what a backslash before an ordinary letter does, which is the part the engines disagree about: an error in Python, Java, Go and Rust, and the letter itself in Perl, JavaScript and Ruby.
Level: 201 · you are building a pattern from text you did not write
The characters¶
| Needs escaping outside a class | \ ^ $ . | ? * + ( ) [ ] { } |
|---|---|
| Needs escaping inside a class | \ ] and, by position, ^ - (see character class) |
| Never needs escaping | / — a delimiter in Perl, JavaScript and Ruby literals, not a metacharacter; - outside a class; , : ; = ! < > @ # (except under (?x)) |
Escaping { and } is the one that varies: an unmatched { is a literal in six engines and an error in Java and Rust, so the backslash is the portable spelling.
Measured¶
Verified output of topic_escaping_and_literal_text_sh.sh — regenerated by tools/run_examples.py, never hand-typed.
construct python perl node ruby java go rust fancy
unescaped dot axb axb axb axb axb axb axb axb
escaped dot no no no no no no no no
dot in a class no no no no no no no no
escaped star 2*3 2*3 2*3 2*3 2*3 2*3 2*3 2*3
escaped brackets [x] [x] [x] [x] [x] [x] [x] [x]
escaped braces a{2} a{2} a{2} a{2} a{2} a{2} a{2} a{2}
escaped backslash a\\b a\\b a\\b a\\b a\\b a\\b a\\b a\\b
hyphen outside a class a-b a-b a-b a-b a-b a-b a-b a-b
slash needs no escape a/b a/b a/b a/b a/b a/b a/b a/b
escaped letter: \e - \u{1B} no \u{1B} \u{1B} - - \u{1B}
escaped letter: \q - q q q - - - -
Reading the table¶
- Rows 1–3.
a.bmatchesaxb;a\.banda[.]bdo not. All eight agree, and both escaped spellings are equally portable — the class is the one that survives being pasted into a shell, where a backslash may be eaten first. - Rows 4–9 are unanimous too: escaped
*,[,],{,},\are literals, and-and/were never special outside a class. - Row 10,
\e. An escape sequence for ESC (U+001B) in Perl, Ruby, Java andfancy-regex. Refused by Python, Go and Rust'sregex. JavaScript matched nothing:\eis the letterethere, and the subject held noe. - Row 11,
\q. A letter with no meaning behind a backslash. Perl, JavaScript and Ruby read it asqand matched. Python, Java, Go and Rust refuse. This is the row that decides how safe an escaping function has to be: in the first three engines, over-escaping is harmless; in the other four, backslashing the wrong letter is a compile error. (Python reserves every\+ ASCII letter as an error unless it is defined, since 3.7.)
The function in each language¶
The keyword page for \Q…\E runs each language's escape function on one string, and the results differ:
Verified output of kw_quote_escape_sh.sh — regenerated by tools/run_examples.py, never hand-typed.
input a.b*c[d]{e}$ f
python a\.b\*c\[d\]\{e\}\$\ f
perl a\.b\*c\[d\]\{e\}\$\ f
ruby a\.b\*c\[d\]\{e\}\$\ f
java \Qa.b*c[d]{e}$ f\E
go a\.b\*c\[d\]\{e\}\$ f
rust a\.b\*c\[d\]\{e\}\$ f
Python, Perl and Ruby escape the space; Go and Rust do not; Java escapes nothing and wraps the text in \Q…\E. Each output is correct for its own engine — and a Python-escaped string handed to Java contains \, which Java refuses as an unknown escape. Escape in the language that will run the pattern, never upstream of it.
The rules¶
- Text from outside the program is escaped before it becomes part of a pattern, with the language's function:
re.escape,quotemeta,Regexp.escape,Pattern.quote,regexp.QuoteMeta,regex::escape. JavaScript'sRegExp.escapearrived in ES2025; before that,s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")is the idiom. - A replacement string from outside is escaped too, against a different set —
$and\— because the replacement is its own language. Or use a function as the replacement, which needs no escaping at all. - Prefer a class to a backslash where both work:
[.]and[$]survive shell quoting, YAML, and a second round of escaping better than\.and\$.
Keywords on this page¶
\Q…\E · Character class · $ · {n,m} · Replacement references.
See also¶
- Security — what an unescaped user string does to a validator.
- Search and replace.