Nesta aula, vamos explorar dois recursos poderosos do shell Bash: here documents (também chamados de heredocs) e here strings. Eles permitem que você forneça entrada multi-linha ou uma string diretamente a um comando, sem precisar criar arquivos temporários ou usar comandos externos como echo e cat com redirecionamentos complexos. Essas construções são essenciais para scripts que precisam gerar configurações, interagir com programas interativos ou simplesmente manter o código mais limpo e legível.

Entenderemos as diferenças entre as formas <<EOF e <<-EOF, veremos como usar <<< para strings curtas, e discutiremos casos de uso comuns, como alimentar comandos SQL, gerar arquivos de configuração e testar programas. Ao final, você terá uma base sólida para aplicar esses recursos em seus próprios scripts.

<<EOF

O here document é uma forma de redirecionar um bloco de texto como entrada padrão (stdin) para um comando. A sintaxe básica é:

comando <<DELIMITADOR
linha 1
linha 2
DELIMITADOR

O DELIMITADOR é um identificador arbitrário (geralmente EOF, mas pode ser qualquer string sem espaços). O conteúdo entre a linha do delimitador e a linha que repete o delimitador é enviado para o comando como entrada. O delimitador deve aparecer em uma linha própria, sem espaços antes ou depois (a menos que você use a variante <<-).

Exemplo simples com cat:

cat <<EOF
Olá, mundo!
Este é um here document.
EOF

Isso exibirá as duas linhas na saída padrão. Aqui, o cat recebe o texto como entrada e o imprime.

Um uso comum é passar múltiplas linhas para um comando que lê do stdin, como wc (contagem de palavras) ou grep:

wc -l <<EOF
linha um
linha dois
linha três
EOF

O resultado será 3, pois há três linhas no here document.

<<-EOF

A variação <<-EOF permite que o delimitador seja precedido por tabulações (tabs) e também remove as tabulações iniciais de cada linha do here document. Isso é útil para manter a indentação do código no script sem que ela seja incluída na entrada.

Exemplo:

if true; then
    cat <<-EOF
    Esta linha está indentada no script,
    mas as tabulações serão removidas.
    EOF
fi

Sem o hífen, a saída incluiria as tabulações. Com <<-, a saída será:

Esta linha está indentada no script,
mas as tabulações serão removidas.

Observação: a remoção de tabulações se aplica a todas as linhas, mas apenas se elas começarem com tab, não espaços. Portanto, para usar esse recurso, é necessário usar tabulações na indentação do here document (muitos editores substituem tabs por espaços, então é preciso configurar para usar tabs).

Outro uso: você pode usar um delimitador com prefixo para evitar expansão de variáveis? Não, isso é feito com aspas no delimitador, como veremos abaixo.

Here strings (<<<)

O here string é uma forma mais simples de redirecionar uma única string (sem quebra de linha explícita) como entrada para um comando. A sintaxe é:

comando <<< "string"

O Bash adiciona automaticamente uma nova linha ao final da string. Isso é útil para passar uma variável ou uma string curta para programas que esperam entrada pelo stdin.

Exemplo com grep:

grep "mundo" <<< "Olá, mundo!"

Isso fará o grep procurar a palavra "mundo" na string fornecida e imprimirá a linha correspondente (a string inteira, pois contém "mundo").

Também é comum usar here strings para alimentar comandos como bc (calculadora) ou sed:

bc <<< "2 + 3"

Resultado: 5.

Uma diferença importante: no here string, as aspas são necessárias se você quiser evitar expansão de variáveis? Na verdade, o conteúdo entre aspas duplas ainda é expandido. Para evitar expansão, use aspas simples:

var="mundo"
# Com aspas duplas, expande a variável:
echo <<< "Olá, $var!"  # Isso não funciona, echo não lê stdin; mas se usar cat:
cat <<< "Olá, $var!"   # Saída: Olá, mundo!
# Com aspas simples, não expande:
cat <<< 'Olá, $var!'   # Saída: Olá, $var!

Casos de uso

Agora que conhecemos as construções, vejamos alguns casos de uso práticos em scripts.

1. Gerar arquivos de configuração

Frequentemente, precisamos criar arquivos de configuração dinâmicos. Um here document permite criar o arquivo com conteúdo variável:

cat > app.conf <<EOF
[servidor]
host = localhost
porta = 8080
usuário = $USER
EOF

O arquivo app.conf será criado com as variáveis expandidas (por exemplo, o nome do usuário). Para evitar expansão, coloque o delimitador entre aspas: <<'EOF'.

2. Interagir com programas interativos

Programas como ftp ou sqlplus podem ser alimentados com comandos via here document:

mysql -u root -p <<EOF
CREATE DATABASE meu_banco;
USE meu_banco;
CREATE TABLE exemplo (id INT);
EOF

Isso executa os comandos SQL sem necessidade de entrada manual.

3. Testar comandos com entrada fixa

Para testar um script que lê do stdin, você pode usar um here string ou here document:

./meu_script.sh <<< "entrada de teste"

Ou com múltiplas linhas:

./meu_script.sh <<EOF
linha 1
linha 2
EOF

4. Evitar usar arquivos temporários

Em vez de criar um arquivo temporário para depois passá-lo a um comando, você pode usar um here document diretamente:

# Em vez de:
# echo "dados" > temp.txt
# comando < temp.txt
# rm temp.txt
comando <<< "dados"

Boas práticas e observações

  • Escolha delimitadores descritivos, como EOF, FIM ou CONFIG, para facilitar a leitura.
  • Se você não quiser que variáveis sejam expandidas, use <<'EOF' (aspas simples no delimitador).
  • Use <<- para manter a indentação do código sem afetar a saída, mas lembre-se de usar tabulações.
  • Here strings são ideais para strings curtas; here documents são melhores para blocos grandes.
  • Evite usar here documents dentro de loops com muitos dados, pois a memória pode ser consumida; prefira redirecionar de arquivos quando possível.

Referências

Exercícios

  1. Escreva um comando que use um here document para criar um arquivo chamado mensagem.txt com o seguinte conteúdo, sem expandir variáveis:

    Olá, $USER!
    Bem-vindo ao curso.
    

    Dica: use aspas no delimitador.

    ✓ Resposta:
    cat > mensagem.txt <<'EOF'
    Olá, $USER!
    Bem-vindo ao curso.
    EOF
    
  2. Use um here string para contar o número de caracteres da string "Hello, world!" usando o comando wc -c. Qual é o resultado?

    ✓ Resposta:
    wc -c <<< "Hello, world!"
    
    O resultado é 14, pois a string tem 13 caracteres + nova linha adicionada pelo here string.
  3. Escreva um script que use um here document com <<-EOF para imprimir uma lista de itens, mas com o script indentado. A saída deve ser:

    Item 1
    Item 2
    

    ✓ Resposta:
    #!/bin/bash
    if true; then
    	cat <<-EOF
    	Item 1
    	Item 2
    	EOF
    fi
    
    Use tabulações para indentar as linhas do here document.
  4. Explique a diferença entre <<EOF e <<-EOF em termos de remoção de tabulações.

    ✓ Resposta: <<-EOF remove todas as tabulações iniciais de cada linha do here document, permitindo que o código fique indentado sem que isso afete a saída. <<EOF mantém as tabulações como parte do texto.
  5. Crie um here document que alimente o comando bc com uma expressão matemática que calcule a área de um círculo de raio 5 (use pi=3.14159). O resultado deve ser exibido.

    ✓ Resposta:
    bc <<EOF
    3.14159 * 5 * 5
    EOF
    
    Resultado: 78.53975