Heredoc: Como Incorporar Strings Multilinhas em Scripts Shell
O que e um Heredoc?
Um heredoc (here document) permite incorporar strings multilinhas diretamente em um script shell. Ele comeca com <<DELIMITADOR e termina quando o delimitador aparece sozinho em uma linha. Comparado a encadear multiplas chamadas echo, heredocs sao muito mais legveis e sao amplamente usados para gerar arquivos de configuracao, executar consultas SQL e enviar comandos via SSH.
Sintaxe Basica
Escreva <<DELIMITADOR, depois o corpo do texto, e em seguida o delimitador de fechamento em sua propria 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) e a escolha convencional.
O delimitador de fechamento deve comecar na coluna zero. Quaisquer espacos ou tabs iniciais impedirao seu reconhecimento, fazendo o script travar aguardando entrada.
A Expansao de Variaveis Esta Ativada por Padrao
Com <<EOF (sem aspas), variaveis e substituicoes de comando dentro do heredoc sao expandidas pelo shell antes da saida.
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 expansao, 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 variaveis shell na saida ->
<<EOF(padrao) - Exibir um template ou trecho de codigo literalmente ->
<<'EOF'
Remover Tabs Iniciais com <<-
Um heredoc padrao preserva todos os espacos em branco iniciais. Com <<-, apenas caracteres tab iniciais sao removidos. Isso permite indentar o corpo do heredoc para combinar com o codigo ao redor sem que a indentacao apareca na saida.
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) sao removidos -- nao espacos. Se seu editor usa indentacao com espacos, voce precisa converter essas linhas para tabs para que o <<- funcione.
Escrevendo em Arquivos
Combine um heredoc com redirecionamento para gerar arquivos de configuracao diretamente a partir de um script.
cat <<EOF > /tmp/config.conf host=localhost port=5432 dbname=mydb EOF
Para adicionar ao inves de sobrescrever, use >>:
cat <<EOF >> /tmp/config.conf user=admin password=secret EOF
Para arquivos que precisam de permissoes root, passe pelo sudo tee. Usar sudo cat <<EOF > /root/file nao 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 Pratico -- 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 variaveis sejam expandidas localmente antes de a string ser enviada ao shell remoto. Use <<'EOF' quando quiser que o shell remoto as expanda.
Exemplo Pratico -- 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 padrao e comum em scripts de inicializacao e jobs em lote que precisam executar multiplas instrucoes SQL em uma unica sessao.
Armadilhas Comuns
Sem espacos 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 comecar na coluna zero (ou use <<- apenas com tabs).
Escapando cifrao para saida literal
Com <<EOF (expansao 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 variavel
Para armazenar um heredoc em uma variavel ao inves de canaliza-lo para um comando, use substituicao de comando com $().
TEXT=$(cat <<EOF texto multilinha armazenado em uma variavel EOF ) echo "$TEXT"