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"