A Bash-szkriptelésben a „here document” (vagy „heredoc”) a bemenet több sorát irányítja át egy parancsnak vagy programnak, mintha csak közvetlenül a terminálba gépelnéd be őket. Hatékony eszköz arra, hogy több soros szöveget ágyazz a szkriptjeidbe anélkül, hogy külső fájlokra vagy bonyolult stringkezelésre lenne szükség.
Határoló: a heredoc a << operátorral kezdődik, amelyet egy határoló szó követ (ezt szokás „jelölőnek” vagy „lezárónak” is nevezni).
Ez a határoló bármilyen szó lehet, amit csak kiválasztasz, de az áttekinthetőség kedvéért gyakran olyasmit használnak, mint az EOF, az END vagy a TEXT.
Olvashatóbb kód érdekében leíró határolót is választhatsz, például END_INSTALLATION_INSTRUCTIONS-t.
Tartalom: a kezdeti << DELIMITER után írod le azt a tartalmat, amelyet át szeretnél irányítani.
Ez lehet több sor szöveg, kód vagy bármi más.
Lezárás: a heredoc akkor ér véget, amikor a határoló szó újra megjelenik egy sorban, egyedül, előtte és utána semmilyen szóköz vagy tabulátor nélkül.
command << DELIMITER
Content line 1
Content line 2
...
Content line N
DELIMITER
<< DELIMITER és a záró DELIMITER között.cat << EOF
This is the first line.
This is the second line.
This is the third line.
EOF
Kimenet:
This is the first line.
This is the second line.
This is the third line.
Ebben a példában:
cat a parancs.<< EOF indítja a heredocot, a határoló pedig az EOF.EOF egy külön sorban zárja le a heredocot.cat ezután kiírja a kapott tartalmat.wc -l << END
Line 1
Line 2
Line 3
END
Kimenet:
3
Itt a wc -l a sorok számát számolja meg.
A heredoc három sort ad bemenetként.
A szkript:
#!/usr/bin/env bash
# Script to process input
while IFS= read -r line; do
echo "Processing: $line"
done
Hívd meg a szkriptet egy interaktív bash-parancssorból, heredoc segítségével:
./your_script << MY_DATA
Item 1
Item 2
Item 3
MY_DATA
Kimenet:
Processing: Item 1
Processing: Item 2
Processing: Item 3
A Bash a heredocon belül végrehajtja a változóbehelyettesítést, a parancsbehelyettesítést és az aritmetikai kiértékelést. Ebben az értelemben a heredocok úgy viselkednek, mint a kettős idézőjelbe tett stringek.
cat << EOF
The value of HOME is $HOME
The current date is $(date)
Two plus two is $((2 + 2))
EOF
Kimenet:
The value of HOME is /home/glennj
The current date is Thu Apr 24 13:47:32 EDT 2025
Two plus two is 4
Ha a határolót idézőjelbe teszed (szimpla vagy dupla idézőjellel), ezek a behelyettesítések elmaradnak. A tartalom szó szerint értelmeződik. Ez olyan, mint a szimpla idézőjelbe tett stringek esetében.
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
Kimenet:
The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))
Ha a << helyett a <<--t használod (a végén lévő kötőjellel), a Bash leveszi a heredoc minden sorának elejéről a tabulátorkaraktereket.
Ez akkor hasznos, ha a heredoc tartalmát behúzva szeretnéd elhelyezni a szkriptben anélkül, hogy ez a kimenetet befolyásolná.
# 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 kimenet úgy jelenik meg, hogy az összes kezdő tabulátor eltűnt belőle:
This line has 1 leading tab.
This line has a leading tab and some spaces.
This line 2 leading tabs.
A szerző nem javasolja ezt a használatot. Bár javíthatja a szkript olvashatóságát,
Egy tipikus felhasználás a súgószöveg biztosítása:
#!/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
A heredocokhoz hasonlóan a here stringek (vagy „herestringek”) is bemenetet adnak egy parancsnak.
Míg azonban a heredocot szövegblokként adod meg, addig a here stringet egyetlen stringként.
A here stringek a <<< "text" szintaxist használják.
tr 'a-z' 'A-Z' <<< "upper case this string"
Kimenet:
UPPER CASE THIS STRING
A heredocokkal ellentétben itt nincs szükség záró határolóra.
Egy here string helyett csővezetéket is használhatsz:
echo "upper case this string" | tr 'a-z' 'A-Z'
Akkor miért használj here stringet?
Vegyük azt az esetet, amikor egy hosszan futó számítás kimeneteként kapod meg a stringet, és az eredményt két külön parancsnak szeretnéd átadni. Csővezetékek használatával kétszer kell lefuttatnod a számítást:
some_long_running_calculation | first_command
some_long_running_calculation | second_command
Hatékonyabb megközelítés, ha elmented a számítás kimenetét (parancsbehelyettesítéssel), majd here stringekkel adod meg a bemenetet a két következő parancsnak:
result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"
Íme egy valós példa erre:
# 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
Figyeld meg a kimenetátirányítás helyét.
A while-ciklus összes kimenete a data.csv fájl végére fűződik.
Mivel ezek csupán az átirányítás egy-egy formái, más átirányítási műveletekkel is kombinálhatók:
cat <<< END_OF_TEXT > output.txt
This is my important text.
END_OF_TEXT
awk '...' <<< "$my_var" >> result.csv
A heredocok rugalmas és kényelmes módot kínálnak a többsoros bemenet kezelésére Bash-szkriptekben. Egyszerűbbé teszik, hogy szöveget és adatokat közvetlenül a szkriptjeidbe ágyazz, így azok önállóbbak és könnyebben olvashatók lesznek.
A here stringek (vagy „herestringek”) a heredocokhoz hasonlók, de egyszerűbb, dinamikusabb szintaxist kínálnak.