Escape sequences across languages
JSON and JavaScript escapes, C and Python string literals, shell quoting, and the double-decoding mistakes that happen when two escape systems meet.
JSON escapes are a closed set
{
"quote": "she said \"hi\"",
"path": "C:\\Users\\dev",
"newline": "line one\nline two",
"tab": "col1\tcol2",
"unicode": "\u20ac \ud83d\ude00",
"control": "\u0007"
}- JSON allows exactly eight escape sequences:
" \ / b f n r t, plus\uXXXX. - A backslash before any other character is invalid JSON —
\din a regular expression string must be written\\d. - Forward slash may be escaped but need not be; the option exists for embedding JSON in markup.
- Control characters below U+0020 must be escaped; they cannot appear literally.
intended JSON : {"re": "\d+"}
written as JS : const s = '{"re": "\\d+"}'; // four slashes in source
written as JSON : {"re": "\\d+"} // two slashes in the documentPer-language escapes
| Language | Escapes | Gotcha |
|---|---|---|
| JSON | \uXXXX, eight named | No \x, no single quotes, no trailing commas |
| JavaScript | \xHH, \u{...}, templates | A template literal also interprets dollar-brace placeholders and backslash escapes |
| Python | \x, \u, \U, raw strings | \d in a normal string is a deprecation warning; use r"\d" |
| C | \xHH, octal \NNN | An octal escape consumes up to three digits eagerly |
| Shell | quoting, not escapes | Single quotes are literal; double quotes expand variables |
| SQL | doubled single quote | 'It''s' — a backslash is not the escape |
| XML | entities, not backslashes | ' for an apostrophe |
import re, json
# a backslash-hungry regular expression
pattern = r"\d{4}-\d{2}-\d{2}" # raw string: no escape processing
re.fullmatch(pattern, "2026-09-18")
# the same value as JSON text needs the backslash doubled
json.dumps({"re": pattern}) # '{"re": "\\d{4}-\\d{2}-\\d{2}"}'Two escape systems at once
The hardest bugs come from escaping for one layer while another is also active — a regex inside a JSON string inside a shell command has three escaping rules applied to the same characters.
# three layers: shell, then curl's JSON, then the server's JSON parser
# single quotes make the shell literal, so only the JSON rules apply
curl -s -X POST https://api.example.com/search \
-H 'Content-Type: application/json' \
-d '{"pattern": "\\d{4}", "path": "a\\b"}'
# build the payload in a file instead of a shell string
# that removes one layer entirely- Prefer a client library over hand-built strings; it escapes for its own layer correctly.
- Prefer a file or stdin over a shell-quoted payload.
- When you must nest, escape from the inside out and test with a value that contains a quote, a backslash and a newline.
- A round-trip test — encode then decode and compare — catches nearly all of these bugs.
⚠️
Never build a shell command by concatenating untrusted input, however many escapes you apply. Use an argument array or a library call. Shell metacharacters survive many naive escaping attempts, and the failure mode is command execution.
FAQ
Can JSON contain a literal newline inside a string?
No. Use
\n. A raw newline is a control character and makes the document invalid, though some lenient parsers accept it.Why did my regex work in Python but fail after JSON parsing?
The backslashes were consumed by the JSON layer. Store the pattern with doubled backslashes in the JSON text, or avoid the extra layer by keeping the pattern out of the payload.
Related
HTML entities and escaping in markup Mojibake: diagnosing and fixing broken text
Last refreshed 2026-09-18.