How to Disable Variable Interpretation in Bash Heredoc for Literal String Output


1 views

When working with bash heredoc (<

# Problematic example with unwanted expansion
cat > config.txt <

The most reliable solution is quoting the delimiter itself. This disables all special interpretation within the heredoc:

cat > nginx_config <<'EOF'
server {
    listen 80;
    server_name $host;  # Now preserved literally
    root /var/www/$path;
}
EOF

While quoting the delimiter is preferred, you can also escape individual dollar signs:

# Method 1: Backslash escape each $
cat > script.sh < demo <

Here's how to properly generate an nginx config with literal variables:

# Correct approach for OP's original problem
cat > /etc/nginx/sites-available/default_php <<'NGINX_CONF'
server {
    listen 80 default;
    server_name _;
    root /var/www/$host;  # Now preserved exactly
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php${PHP_VERSION}-fpm.sock;
    }
}
NGINX_CONF

For mixed content (some variables expanded, others literal), consider these patterns:

# Hybrid approach using different quoting
ACTUAL_VAR="value"
cat > output <

The key insight is that heredoc behavior changes fundamentally based on whether the delimiter is quoted. For configuration file generation where exact string preservation is crucial, always quote your heredoc delimiters.


When working with bash heredocs, you might encounter situations where you need to prevent variable expansion. The shell automatically expands variables within heredoc blocks, which can cause issues when you want to preserve literal dollar signs.

cat > example.sh <

Method 1: Quoting the Heredoc Delimiter

The most straightforward solution is to quote the heredoc delimiter:

cat > /etc/nginx/sites-available/default_php <<'END'
server {
    listen 80 default;
    server_name _;
    root /var/www/$host;  # $host will remain literal
}
END

Method 2: Escaping Individual Dollar Signs

If you only need to escape specific variables:

cat > config.txt <

Method 3: Using a Backslash Before EOF

An alternative syntax that works in most shells:

cat << \EOF > output.txt
This $variable won't expand
Neither will this ${another_one}
EOF

Selective Expansion with Mixed Quotes

For complex cases where you need some variables expanded and others not:

name="Server1"
cat << "EOF" > config.cfg
Hostname: $name       # Won't expand
IP: "$(hostname -I)"  # Won't execute
EOF

cat << EOF > config.cfg
Hostname: $name       # Will expand
IP: "$(hostname -I)"  # Will execute
EOF

Here Documents in Functions

When using heredocs within functions, the same rules apply:

generate_config() {
    local port=8080
    cat << 'EOT' > nginx.conf
server {
    listen ${port};  # Won't expand
    # ...
}
EOT
}
  • The quoting must be on the delimiter word itself, not the << operator
  • Mixing quoted and unquoted delimiters in the same script can cause confusion
  • Some older shells might have slightly different behavior

There's no performance difference between the quoted and unquoted versions - the parsing happens at script interpretation time, not during execution.