Heredoc: Como Incorporar Strings Multilinhas em Scripts Shell

Heredoc: Como Incorporar Strings Multilinhas em Scripts Shell

O que é um Heredoc?

Um heredoc (here document) permite incorporar strings multilinhas diretamente em um script shell. Ele começa com <<DELIMITADOR e termina quando o delimitador aparece sozinho em uma linha. Comparado a encadear múltiplas chamadas echo, heredocs são muito mais legveis e são amplamente usados para gerar arquivos de configuração, executar consultas SQL e enviar comandos via SSH.

Sintaxe Básica

Escreva <<DELIMITADOR, depois o corpo do texto, e em seguida o delimitador de fechamento em sua própria linha.

cat <<EOF
Primeira linha de texto
Segunda linha de texto
Terceira linha de texto
EOF
Primeira linha de texto
Segunda linha de texto
Terceira linha de texto

O delimitador pode ser qualquer string -- EOF, END, HEREDOC -- mas EOF (End Of File) é a escolha convencional.

O delimitador de fechamento deve começar na coluna zero. Quaisquer espaços ou tabs iniciais impedirão seu reconhecimento, fazendo o script travar aguardando entrada.

A Expansão de Variáveis Está Ativada por Padrão

Com <<EOF (sem aspas), variáveis e substituições de comando dentro do heredoc são expandidas pelo shell antes da saída.

NAME="Alice"
TODAY=$(date +%Y-%m-%d)
cat <<EOF
Ola, $NAME
Hoje e $TODAY
EOF
Ola, Alice
Hoje e 2026-06-01

Para desativar a expansão, coloque o delimitador entre aspas simples.

NAME="Alice"
cat <<'EOF'
Ola, $NAME
$(date) nao e expandido
EOF
Ola, $NAME
$(date) nao e expandido

Quando usar qual

  • Incorporar variáveis shell na saída -> <<EOF (padrão)
  • Exibir um template ou trecho de código literalmente -> <<'EOF'

Remover Tabs Iniciais com <<-

Um heredoc padrão preserva todos os espaços em branco iniciais. Com <<-, apenas caracteres tab iniciais são removidos. Isso permite indentar o corpo do heredoc para combinar com o código ao redor sem que a indentação apareça na saída.

if true; then
	cat <<-EOF
	Bloco indentado
	Tabs sao removidos da saida
	EOF
fi
Bloco indentado
Tabs sao removidos da saida

Apenas caracteres tab (\t) são removidos -- não espaços. Se seu editor usa indentação com espaços, você precisa converter essas linhas para tabs para que o <<- funcione.

Escrevendo em Arquivos

Combine um heredoc com redirecionamento para gerar arquivos de configuração diretamente a partir de um script.

cat <<EOF > /tmp/config.conf
host=localhost
port=5432
dbname=mydb
EOF

Para adicionar ao invés de sobrescrever, use >>:

cat <<EOF >> /tmp/config.conf
user=admin
password=secret
EOF

Para arquivos que precisam de permissões root, passe pelo sudo tee. Usar sudo cat <<EOF > /root/file não funciona porque o shell abre o alvo do redirecionamento antes do sudo ter efeito.

cat <<EOF | sudo tee /etc/myapp/config.conf
host=localhost
port=5432
EOF

Exemplo Prático -- Executando Comandos via SSH

ssh user@server <<EOF
echo "Iniciando deploy"
cd /var/www/myapp
git pull origin main
systemctl restart myapp
EOF

Use <<EOF quando quiser que as variáveis sejam expandidas localmente antes de a string ser enviada ao shell remoto. Use <<'EOF' quando quiser que o shell remoto as expanda.

Exemplo Prático -- Enviando Consultas ao MySQL

mysql -u root -p mydb <<EOF
SELECT id, name FROM users WHERE active = 1;
UPDATE users SET last_login = NOW() WHERE id = 42;
EOF

Esse padrão é comum em scripts de inicialização e jobs em lote que precisam executar múltiplas instruções SQL em uma única sessão.

Armadilhas Comuns

Sem espaços ou tabs antes do delimitador de fechamento

# Errado: o EOF de fechamento tem espacos iniciais e nunca e reconhecido
cat <<EOF
conteudo
  EOF
EOF

O delimitador de fechamento deve começar na coluna zero (ou use <<- apenas com tabs).

Escapando cifrão para saída literal

Com <<EOF (expansão ativada), prefixe $ com uma barra invertida para exibi-lo literalmente.

cat <<EOF
Variavel do diretorio home: \$HOME
Valor real: $HOME
EOF
Variavel do diretorio home: $HOME
Valor real: /home/alice

Capturando um heredoc em uma variável

Para armazenar um heredoc em uma variável ao invés de canalizá-lo para um comando, use substituição de comando com $().

TEXT=$(cat <<EOF
texto
multilinha
armazenado em uma variavel
EOF
)
echo "$TEXT"

Próximas Leituras