Trilhas
/
Bash
Bash
/
Programa
/
Here documents
He

Here documents em Bash

{one: "1 exercício", many: "%{count} de exercícios", other: "%{count} exercícios"}

Sobre Here documents

Na programação em Bash, um "here document" (ou "heredoc") redireciona várias linhas de entrada para um comando ou programa, como se você estivesse digitando diretamente no terminal. É uma ferramenta poderosa para embutir texto de várias linhas nos seus scripts sem precisar de arquivos externos ou de manipulação complexa de strings.

Características e sintaxe principais

  1. Delimitador: um heredoc começa com o operador << seguido de uma palavra delimitadora (muitas vezes chamada de "marcador" ou "terminador"). Esse delimitador pode ser qualquer palavra que você escolher, mas é comum usar algo como EOF, END ou TEXT para maior clareza. Para um código mais legível, você pode usar algo descritivo como delimitador, por exemplo END_INSTALLATION_INSTRUCTIONS.

  2. Conteúdo: depois do << DELIMITER inicial, você escreve o conteúdo que quer redirecionar. Pode ser várias linhas de texto, código ou qualquer outra coisa.

  3. Terminação: o heredoc termina quando a palavra delimitadora aparece de novo em uma linha sozinha, sem espaços em branco antes ou depois.

Sintaxe básica

command << DELIMITER
  Content line 1
  Content line 2
  ...
  Content line N
DELIMITER

Como funciona

  • O Bash lê todas as linhas entre o << DELIMITER inicial e o DELIMITER final.
  • O Bash conecta esse conteúdo à entrada padrão do comando.
  • O comando processa essa entrada como se ela estivesse vindo do teclado.

Exemplo 1: saída de texto simples

cat << EOF
This is the first line.
This is the second line.
This is the third line.
EOF

Saída:

This is the first line.
This is the second line.
This is the third line.

Neste exemplo:

  • cat é o comando.
  • << EOF inicia o heredoc com EOF como delimitador.
  • As três linhas de texto são o conteúdo.
  • O EOF sozinho em uma linha encerra o heredoc.
  • O cat então exibe o conteúdo que recebeu.

Exemplo 2: uso com o wc (contagem de palavras)

wc -l << END
Line 1
Line 2
Line 3
END

Saída:

3

Aqui, o wc -l conta o número de linhas. O heredoc fornece as três linhas como entrada.

Exemplo 3: passando dados para um script

O script:

#!/usr/bin/env bash

# Script to process input
while IFS= read -r line; do
  echo "Processing: $line"
done

Chame o script de um prompt interativo do bash com um heredoc:

./your_script << MY_DATA
Item 1
Item 2
Item 3
MY_DATA

Saída:

Processing: Item 1
Processing: Item 2
Processing: Item 3

Variações e recursos avançados

Conteúdo literal

O Bash realiza expansão de variáveis, substituição de comando e expansão aritmética dentro de um heredoc. Nesse sentido, os heredocs funcionam como strings entre aspas duplas.

cat << EOF
The value of HOME is $HOME
The current date is $(date)
Two plus two is $((2 + 2))
EOF

Saída:

The value of HOME is /home/glennj
The current date is Thu Apr 24 13:47:32 EDT 2025
Two plus two is 4

Quando o delimitador está entre aspas (usando aspas simples ou duplas), essas expansões não acontecem. O conteúdo é tratado de forma literal. Isso é como strings entre aspas simples.

cat << 'EOF'
The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))
EOF

Saída:

The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))

Removendo tabs iniciais

Se você usar <<- (com um hífen no final) em vez de <<, o Bash vai remover qualquer tab inicial de cada linha do heredoc. Isso é útil para indentar o conteúdo do heredoc dentro do seu script sem afetar a saída.

# Note, the leading whitespace is tab characters only, not spaces!
# The ending delimiter can have leading tabs as well.
cat <<- END
	This line has 1 leading tab.
	  This line has a leading tab and some spaces.
		This line 2 leading tabs.
	END

A saída é exibida com todos os tabs iniciais removidos:

This line has 1 leading tab.
    This line has a leading tab and some spaces.
This line 2 leading tabs.
Caution

O autor não recomenda esse uso. Embora ele possa melhorar a legibilidade do script,

  1. é fácil substituir os tabs por espaços sem querer (seu editor pode fazer isso automaticamente), e
  2. é difícil perceber a diferença entre espaços e tabs.

Quando usar here documents

  • Entrada com várias linhas: quando você precisa fornecer várias linhas de texto para um comando.
  • Arquivos de configuração: embutir pequenos trechos de configuração dentro de um script.
  • Geração de código: criar código na hora dentro de um script.
  • Interações com scripts: simular a entrada do usuário para programas interativos.
  • Evitar arquivos externos: quando você quer evitar criar arquivos temporários.

Um uso típico pode ser fornecer um texto de ajuda:

#!/usr/bin/env bash

usage() {
    cat << END_USAGE
Refresh database tables.

usage: ${0##*/} [-h|--help] [-A|--no-archive]

where: --no-archive flag will _skip_ the archive jobs
END_USAGE
}

# ... parsing command line options here ...

if [[ $flag_help == "true" ]]; then
  usage
  exit 0
fi

Possíveis desvantagens

  • Documentos embutidos grandes podem deixar seu código mais difícil de ler. Pode ser melhor publicar seu script com a documentação em arquivos separados.
  • Here documents podem quebrar o fluxo do código. Você pode estar em uma seção de código bastante aninhada quando quer passar algum texto para um programa. A indentação do heredoc pode parecer estranha em comparação com o código ao redor.

Here strings

Assim como os here documents, os here strings (ou "herestrings") fornecem entrada para um comando. No entanto, enquanto os heredocs são fornecidos como um bloco de texto, os herestrings são fornecidos como uma única string de texto. Here strings usam a sintaxe <<< "text".

tr 'a-z' 'A-Z' <<< "upper case this string"

Saída:

UPPER CASE THIS STRING

Ao contrário dos heredocs, nenhum delimitador final é necessário.

Por que usar here strings?

Você pode usar um pipeline em vez de um here string:

echo "upper case this string" | tr 'a-z' 'A-Z'

Então por que usar um here string?

Considere o caso em que você obtém a string como saída de um cálculo demorado e quer alimentar o resultado a dois comandos separados. Usando pipelines, você precisa executar o cálculo duas vezes:

some_long_running_calculation | first_command
some_long_running_calculation | second_command

Uma abordagem mais eficiente é capturar a saída do cálculo (usando substituição de comando) e usar here strings para fornecer entrada aos dois comandos seguintes:

result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"

Aqui está uma aplicação real desse exemplo:

  • capturar a resposta JSON de uma consulta a uma API REST (que é paginada),
  • fornecer os dados JSON a um programa jq para analisar os resultados e gravá-los em um arquivo, e depois
  • fornecer os dados JSON a outro programa jq para determinar a URL da próxima consulta.
# initialize the output CSV file
echo "ID,VALUE" > data.csv

url='https//example.com/api/query?page=1'

while true; do
  json=$( curl "$url" )

  # convert the results part of the response into CSV
  jq -r '.results[] | [.id, .value] | @csv' <<< "$json"

  # get the URL for the next page
  url=$( jq -r '.next_url // ""' <<< "$json" )
  if [[ "$url" == "" ]]; then
    break
  fi
done >> data.csv

Repare na posição do redirecionamento de saída. Toda a saída do laço while será anexada ao arquivo data.csv.

Heredocs e herestrings como redirecionamento

Como essas são apenas formas de redirecionamento, elas podem ser combinadas com outras operações de redirecionamento:

cat <<< END_OF_TEXT > output.txt
This is my important text.
END_OF_TEXT

awk '...' <<< "$my_var" >> result.csv

Em resumo

Here documents (ou "heredocs") são uma forma flexível e conveniente de gerenciar entrada com várias linhas em scripts Bash. Eles simplificam o processo de embutir texto e dados diretamente nos seus scripts, tornando-os mais autocontidos e fáceis de ler.

Here strings (ou "herestrings") são parecidos com here documents, mas oferecem uma sintaxe mais simples e mais dinâmica.

Editar via GitHub O link abre em uma nova janela ou aba