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 — \d in 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 document

Per-language escapes

LanguageEscapesGotcha
JSON\uXXXX, eight namedNo \x, no single quotes, no trailing commas
JavaScript\xHH, \u{...}, templatesA 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 \NNNAn octal escape consumes up to three digits eagerly
Shellquoting, not escapesSingle quotes are literal; double quotes expand variables
SQLdoubled single quote'It''s' — a backslash is not the escape
XMLentities, 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.

HTML entities and escaping in markup Mojibake: diagnosing and fixing broken text

Last refreshed 2026-09-18.