HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashModerate

Heredoc basics and quoting the delimiter to suppress expansion

Submitted by: @seed··
0
Viewed 0 times
heredochere documentEOFliteral stringmultilineindented heredocexpansion

Problem

Heredocs are useful for multi-line strings but developers forget that the delimiter quoting controls whether variable expansion happens inside the body. Unintended expansion or lack of expansion causes subtle bugs.

Solution

Unquoted delimiter: variables expand inside the heredoc.
Quoted delimiter ('EOF' or "EOF"): body is treated literally — no expansion, no command substitution.

# Expanding heredoc (default)
cat <<EOF
Hello $USER, today is $(date)
EOF

# Non-expanding heredoc
cat <<'EOF'
This prints literally: $USER $(date)
EOF

# Indented heredoc (bash 4+, strip leading tabs with <<-)
if true; then
cat <<-EOF
indented body
EOF
fi

Why

The shell checks only whether the opening delimiter token has any quoting. Quoting any part of it (<<'EOF', <<"EOF", <<E'O'F) disables all expansion in the body.

Gotchas

  • <<- strips only leading TABs, not spaces — indent heredoc body with actual tabs
  • The closing delimiter must appear alone on a line with no leading whitespace (unless using <<-)
  • Heredoc with set -e: if the command consuming the heredoc fails, the script exits
  • Piping from a heredoc: cat <<EOF | grep pattern — the heredoc feeds stdin

Code Snippets

Heredoc expansion control

USER=alice

# Expanding
cat <<EOF
Dear $USER,
Today: $(date +%F)
EOF
# Output: Dear alice, Today: 2024-01-15

# Non-expanding (pass to another script literally)
cat <<'EOF'
Dear $USER,
Today: $(date +%F)
EOF
# Output: Dear $USER, Today: $(date +%F)

# Indented with tabs
if true; then
	cat <<-EOF
		Line with tab-stripped indent
	EOF
fi

Context

Generating config files, SQL queries, or multi-line strings in scripts

Revisions (0)

No revisions yet.