In der Bash-Skripterstellung leitet ein „Here-Dokument“ (oder „Heredoc“) mehrere Eingabezeilen an einen Befehl oder ein Programm um, als würdest du sie direkt im Terminal eintippen. Es ist ein leistungsfähiges Werkzeug, um mehrzeiligen Text in deine Skripte einzubetten, ohne externe Dateien oder komplizierte String-Manipulation zu brauchen.
Trennzeichen: Ein Heredoc beginnt mit dem Operator <<, gefolgt von einem Trennwort (oft „Marker“ oder „Terminator“ genannt).
Dieses Trennzeichen kann ein beliebiges Wort sein, aber üblicherweise nimmst du etwas wie EOF, END oder TEXT, damit es klar erkennbar ist.
Für besser lesbaren Code kannst du etwas Beschreibendes als Trennzeichen verwenden, zum Beispiel END_INSTALLATION_INSTRUCTIONS.
Inhalt: Nach dem einleitenden << DELIMITER schreibst du den Inhalt, den du umleiten möchtest.
Das können mehrere Zeilen Text, Code oder irgendetwas anderes sein.
Ende: Das Heredoc endet, wenn das Trennwort erneut in einer eigenen Zeile auftaucht, ohne führende oder nachfolgende Leerzeichen.
command << DELIMITER
Content line 1
Content line 2
...
Content line N
DELIMITER
<< DELIMITER und dem abschließenden DELIMITER.cat << EOF
This is the first line.
This is the second line.
This is the third line.
EOF
Ausgabe:
This is the first line.
This is the second line.
This is the third line.
In diesem Beispiel:
cat ist der Befehl.<< EOF startet das Heredoc mit EOF als Trennzeichen.EOF in einer eigenen Zeile beendet das Heredoc.cat den empfangenen Inhalt aus.wc -l << END
Line 1
Line 2
Line 3
END
Ausgabe:
3
Hier zählt wc -l die Anzahl der Zeilen.
Das Heredoc liefert die drei Zeilen als Eingabe.
Das Skript:
#!/usr/bin/env bash
# Script to process input
while IFS= read -r line; do
echo "Processing: $line"
done
Rufe das Skript mit einem Heredoc von einer interaktiven Bash-Eingabeaufforderung aus auf:
./your_script << MY_DATA
Item 1
Item 2
Item 3
MY_DATA
Ausgabe:
Processing: Item 1
Processing: Item 2
Processing: Item 3
Bash führt innerhalb eines Heredocs Variablenexpansion, Befehlssubstitution und arithmetische Expansion durch. In diesem Sinn verhalten sich Heredocs wie Strings in doppelten Anführungszeichen.
cat << EOF
The value of HOME is $HOME
The current date is $(date)
Two plus two is $((2 + 2))
EOF
Ausgabe:
The value of HOME is /home/glennj
The current date is Thu Apr 24 13:47:32 EDT 2025
Two plus two is 4
Wenn das Trennzeichen in Anführungszeichen steht (einfache oder doppelte Anführungszeichen), werden diese Expansionen verhindert. Der Inhalt wird wörtlich genommen. Das ist wie bei Strings in einfachen Anführungszeichen.
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
Ausgabe:
The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))
Wenn du <<- (mit einem Bindestrich am Ende) statt << verwendest, entfernt Bash alle führenden Tabulatorzeichen aus jeder Zeile des Heredocs.
Das ist nützlich, um den Heredoc-Inhalt in deinem Skript einzurücken, ohne die Ausgabe zu beeinflussen.
# 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
Die Ausgabe wird ohne alle führenden Tabs gedruckt:
This line has 1 leading tab.
This line has a leading tab and some spaces.
This line 2 leading tabs.
Der Autor empfiehlt diese Verwendung nicht. Sie kann zwar die Lesbarkeit des Skripts verbessern,
Ein typischer Anwendungsfall könnte sein, einen Hilfetext bereitzustellen:
#!/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
Wie Here-Dokumente liefern Here-Strings (oder „Herestrings“) eine Eingabe an einen Befehl.
Während Heredocs jedoch als Textblock übergeben werden, werden Herestrings als einzelner String übergeben.
Here-Strings verwenden die Syntax <<< "text".
tr 'a-z' 'A-Z' <<< "upper case this string"
Ausgabe:
UPPER CASE THIS STRING
Anders als bei Heredocs ist kein abschließendes Trennzeichen nötig.
Statt eines Here-Strings kannst du eine Pipeline verwenden:
echo "upper case this string" | tr 'a-z' 'A-Z'
Warum also einen Here-String verwenden?
Stell dir vor, du bekommst den String als Ausgabe einer lang laufenden Berechnung, und du willst das Ergebnis an zwei separate Befehle weitergeben. Mit Pipelines musst du die Berechnung zweimal ausführen:
some_long_running_calculation | first_command
some_long_running_calculation | second_command
Effizienter ist es, die Ausgabe der Berechnung aufzufangen (mit Befehlssubstitution) und Here-Strings zu verwenden, um die beiden nachfolgenden Befehle mit Eingabe zu versorgen:
result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"
Hier ist eine praktische Anwendung dieses Beispiels:
# 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
Beachte die Position der Ausgabeumleitung.
Alle Ausgaben der while-Schleife werden an die Datei data.csv angehängt.
Da es sich nur um Formen der Umleitung handelt, lassen sie sich mit anderen Umleitungsoperationen kombinieren:
cat <<< END_OF_TEXT > output.txt
This is my important text.
END_OF_TEXT
awk '...' <<< "$my_var" >> result.csv
Here-Dokumente (oder „Heredocs“) sind eine flexible und bequeme Möglichkeit, mehrzeilige Eingaben in Bash-Skripten zu verwalten. Sie vereinfachen es, Text und Daten direkt in deine Skripte einzubetten, wodurch diese eigenständiger und leichter lesbar werden.
Here-Strings (oder „Herestrings“) sind wie Here-Dokumente, bieten aber eine einfachere und dynamischere Syntax.