Skip to content

syntax: a quoted heredoc processes backslash escapes #1390

Closed

Description

@blairham

A heredoc with a quoted delimiter must be literal — POSIX: "if the delimiter is quoted, the here-document lines shall not be expanded". Backslash escapes are processed anyway.

$ gosh -c "cat <<'X'
a\b c\$d
X"
a� c$d
$ bash -c "cat <<'X'
a\b c\$d
X"
a\b c\$d
in the heredoc gosh bash
a� a� a�
a\b a� a\b
a\$b a$b a\$b
a\`b a`b a\`b
a"b, a'b, `a
b`, line-continuation same same

That is exactly the escape set an unquoted heredoc processes (\, \$, \`), so the quoted form appears to be taking the unquoted path for backslashes only. Everything else about quoting is correct: $HOME, $(cmd), `cmd` and $((1+1)) all stay literal under <<'X' and all expand under <<X, matching bash.

The consequence is that cat > file <<'EOF' — the idiom whose whole point is that the content is not interpreted — writes something other than what it was given, with no error and exit 0. It bites anything with a doubled backslash or an escaped $: shell and awk scripts, regexes whose source spelling is \d (JS, Java, JSON), Windows paths, LaTeX, printf formats, Makefile recipes.

Adjacent and closed: #515, #557.

Found by a bash-vs-gosh differential sweep (128 snippets, each run direct and through eval) while integrating interp as the substrate of a shell. Reproduced on gosh@v3.13.2-0.20260813221317-a04df9f0d4b8 against bash 5.3.15 on darwin/arm64. Happy to send a PR if the direction looks right.

Activity

  1. added a commit that references this issue on Aug 22, 2026
    3c519a1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      ⌂ 换网址