patternbashModerate
Heredoc basics and quoting the delimiter to suppress expansion
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
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
fiContext
Generating config files, SQL queries, or multi-line strings in scripts
Revisions (0)
No revisions yet.