Nella scrittura di script Bash, un «here document» (o «heredoc») reindirizza più righe di input a un comando o a un programma, come se le stessi digitando direttamente nel terminale. È uno strumento potente per incorporare testo su più righe all'interno degli script senza bisogno di file esterni o di manipolazioni complesse delle stringhe.
Delimitatore: un heredoc inizia con l'operatore << seguito da una parola delimitatrice (spesso chiamata «marcatore» o «terminatore»).
Questa parola delimitatrice può essere qualsiasi parola tu scelga, ma è comune usarne una come EOF, END o TEXT per chiarezza.
Per avere un codice più leggibile, puoi usare come delimitatore qualcosa di descrittivo, per esempio END_INSTALLATION_INSTRUCTIONS.
Contenuto: dopo il << DELIMITER iniziale, scrivi il contenuto che vuoi reindirizzare.
Può essere più righe di testo, codice o qualsiasi altra cosa.
Terminazione: l'heredoc termina quando la parola delimitatrice compare di nuovo su una riga da sola, senza spazi bianchi iniziali o finali.
command << DELIMITER
Content line 1
Content line 2
...
Content line N
DELIMITER
<< DELIMITER iniziale e il DELIMITER finale.cat << EOF
This is the first line.
This is the second line.
This is the third line.
EOF
Output:
This is the first line.
This is the second line.
This is the third line.
In questo esempio:
cat è il comando.<< EOF avvia l'heredoc con EOF come delimitatore.EOF su una riga da sola termina l'heredoc.cat scrive poi in output il contenuto che ha ricevuto.wc -l << END
Line 1
Line 2
Line 3
END
Output:
3
Qui wc -l conta il numero di righe.
L'heredoc fornisce le tre righe come input.
Lo script:
#!/usr/bin/env bash
# Script to process input
while IFS= read -r line; do
echo "Processing: $line"
done
Chiama lo script da un prompt bash interattivo con un heredoc:
./your_script << MY_DATA
Item 1
Item 2
Item 3
MY_DATA
Output:
Processing: Item 1
Processing: Item 2
Processing: Item 3
Bash esegue l'espansione delle variabili, la sostituzione dei comandi e l'espansione aritmetica all'interno di un heredoc. In questo senso, gli heredoc si comportano come le stringhe tra doppi apici.
cat << EOF
The value of HOME is $HOME
The current date is $(date)
Two plus two is $((2 + 2))
EOF
Output:
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 il delimitatore è tra apici (con virgolette singole o doppie), queste espansioni non avvengono. Il contenuto viene preso alla lettera. È come con le stringhe tra apici singoli.
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
Output:
The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))
Se usi <<- (con un trattino finale) invece di <<, Bash rimuove i caratteri di tabulazione iniziali da ogni riga dell'heredoc.
È utile per indentare il contenuto dell'heredoc all'interno dello script senza influire sull'output.
# 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
L'output viene stampato con tutte le tabulazioni iniziali rimosse:
This line has 1 leading tab.
This line has a leading tab and some spaces.
This line 2 leading tabs.
L'autore non consiglia questo uso. Anche se può migliorare la leggibilità dello script,
Un uso tipico potrebbe essere fornire un testo di aiuto:
#!/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
Come gli here document, le here string (o «herestring») forniscono input a un comando.
Tuttavia, mentre gli heredoc vengono forniti come un blocco di testo, le herestring vengono fornite come una singola stringa di testo.
Le here string usano la sintassi <<< "text".
tr 'a-z' 'A-Z' <<< "upper case this string"
Output:
UPPER CASE THIS STRING
A differenza degli heredoc, non è richiesto un delimitatore finale.
Al posto di una here string si può usare una pipeline:
echo "upper case this string" | tr 'a-z' 'A-Z'
Quindi perché usare una here string?
Considera il caso in cui ottieni la stringa come output di un calcolo molto lungo e vuoi passare il risultato a due comandi separati. Usando le pipeline, devi eseguire il calcolo due volte:
some_long_running_calculation | first_command
some_long_running_calculation | second_command
Un approccio più efficiente è catturare l'output del calcolo (usando la sostituzione dei comandi) e usare le here string per fornire l'input ai due comandi successivi:
result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"
Ecco un'applicazione reale di quell'esempio:
# 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
Nota la posizione del reindirizzamento dell'output.
Tutto l'output del ciclo while viene aggiunto al file data.csv.
Dato che sono solo forme di reindirizzamento, si possono combinare con altre operazioni di reindirizzamento:
cat <<< END_OF_TEXT > output.txt
This is my important text.
END_OF_TEXT
awk '...' <<< "$my_var" >> result.csv
Gli here document (o «heredoc») sono un modo flessibile e comodo per gestire input su più righe negli script Bash. Semplificano il processo di incorporare testo e dati direttamente negli script, rendendoli più autonomi e più facili da leggere.
Le here string (o «herestring») sono simili agli here document, ma offrono una sintassi più semplice e più dinamica.