Na programação em Bash, um here document (ou heredoc) redireciona várias linhas de entrada para um comando ou programa, como se as estivesses a escrever diretamente no terminal. É uma ferramenta poderosa para incorporar texto com várias linhas nos teus scripts sem precisares de ficheiros externos nem de manipulação complexa de strings.
Delimitador: um heredoc começa com o operador << seguido de uma palavra delimitadora (a que se chama muitas vezes "marcador" ou "terminador").
Este delimitador pode ser a palavra que quiseres, mas é comum usar algo como EOF, END ou TEXT para maior clareza.
Para um código mais legível, podes usar algo descritivo como delimitador, por exemplo END_INSTALLATION_INSTRUCTIONS.
Conteúdo: depois do << DELIMITER inicial, escreves o conteúdo que queres redirecionar.
Pode ser várias linhas de texto, código ou qualquer outra coisa.
Terminação: o heredoc termina quando a palavra delimitadora volta a aparecer sozinha numa linha, sem espaços em branco antes nem depois.
command << DELIMITER
Content line 1
Content line 2
...
Content line N
DELIMITER
<< DELIMITER inicial e o DELIMITER final.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.EOF sozinho numa linha termina o heredoc.cat imprime então o conteúdo que recebeu.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.
O script:
#!/usr/bin/env bash
# Script to process input
while IFS= read -r line; do
echo "Processing: $line"
done
Chama o script a partir de um prompt bash interativo 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
O Bash efetua expansão de variáveis, substituição de comandos e expansão aritmética dentro de um heredoc. Neste sentido, os heredocs comportam-se 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 (simples ou duplas), estas expansões são impedidas. O conteúdo é interpretado literalmente. É como acontece com as 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))
Se usares <<- (com um hífen no fim) em vez de <<, o Bash remove todos os carateres de tabulação iniciais de cada linha do heredoc.
Isto é útil para indentar o conteúdo do heredoc dentro do 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 é impressa com todas as tabulações iniciais removidas:
This line has 1 leading tab.
This line has a leading tab and some spaces.
This line 2 leading tabs.
O autor não recomenda esta utilização. Embora possa melhorar a legibilidade do script,
Uma utilização típica pode ser fornecer algum 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
Tal como os here documents, as here strings (ou herestrings) fornecem entrada a um comando.
No entanto, enquanto os heredocs são dados como um bloco de texto, as here strings são dadas como uma única string de texto.
As 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, não é necessário nenhum delimitador final.
Podes usar um pipeline em vez de uma here string:
echo "upper case this string" | tr 'a-z' 'A-Z'
Então porque usar uma here string?
Considera o caso em que obténs a string como saída de um cálculo demorado e queres passar o resultado a dois comandos separados. Com pipelines, tens de 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 comandos) e usar here strings para fornecer entrada aos dois comandos seguintes:
result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"
Eis uma aplicação real desse exemplo:
# 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
Repara na posição do redirecionamento da saída.
Toda a saída do ciclo while será acrescentada ao ficheiro data.csv.
Como são apenas formas de redirecionamento, podem ser combinados 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
Os here documents (ou heredocs) são uma forma flexível e prática de gerir entrada com várias linhas em scripts Bash. Simplificam o processo de incorporar texto e dados diretamente nos teus scripts, tornando-os mais autónomos e mais fáceis de ler.
As here strings (ou herestrings) são como os here documents, mas oferecem uma sintaxe mais simples e mais dinâmica.