Bashスクリプトでは、「ヒアドキュメント」(「heredoc」とも呼びます)を使うと、複数行の入力を、まるでターミナルに直接入力しているかのように、コマンドやプログラムに渡すことができます。 外部ファイルや複雑な文字列操作を必要とせず、スクリプトの中に複数行のテキストを埋め込める強力な仕組みです。
区切り文字:ヒアドキュメントは、<<演算子に続けて区切りとなる単語(「マーカー」や「ターミネーター」とも呼ばれます)を書くところから始まります。
この区切り文字は好きな単語でかまいませんが、わかりやすさのためにEOFやEND、TEXTなどを使うのが一般的です。
コードをより読みやすくしたいなら、END_INSTALLATION_INSTRUCTIONSのように、内容を表す説明的な単語を区切り文字にするとよいでしょう。
内容:最初の<< DELIMITERのあとに、リダイレクトしたい内容を書きます。
テキストでもコードでも、何行になってもかまいません。
終了:区切り文字が、前後に空白のない単独の行として再び現れると、ヒアドキュメントは終わります。
command << DELIMITER
Content line 1
Content line 2
...
Content line N
DELIMITER
<< DELIMITERと終了のDELIMITERのあいだにあるすべての行を読み取ります。cat << EOF
This is the first line.
This is the second line.
This is the third line.
EOF
出力:
This is the first line.
This is the second line.
This is the third line.
この例では:
catがコマンドです。<< EOFで、EOFを区切り文字としてヒアドキュメントを開始します。EOFがヒアドキュメントを終了します。catが受け取った内容を出力します。wc -l << END
Line 1
Line 2
Line 3
END
出力:
3
ここでは、wc -lが行数を数えています。
ヒアドキュメントが、その3行を入力として渡します。
スクリプト:
#!/usr/bin/env bash
# Script to process input
while IFS= read -r line; do
echo "Processing: $line"
done
対話的なbashプロンプトから、ヒアドキュメントを使ってスクリプトを呼び出します:
./your_script << MY_DATA
Item 1
Item 2
Item 3
MY_DATA
出力:
Processing: Item 1
Processing: Item 2
Processing: Item 3
Bashは、ヒアドキュメントの中でも変数展開、コマンド置換、算術展開を行います。 この意味で、ヒアドキュメントは二重引用符で囲んだ文字列のように振る舞います。
cat << EOF
The value of HOME is $HOME
The current date is $(date)
Two plus two is $((2 + 2))
EOF
出力:
The value of HOME is /home/glennj
The current date is Thu Apr 24 13:47:32 EDT 2025
Two plus two is 4
区切り文字を引用符で囲むと(シングルクォートでもダブルクォートでも)、これらの展開は行われません。 内容はそのままの文字として扱われます。 これはシングルクォートで囲んだ文字列のようなものです。
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
出力:
The value of $HOME is not expanded here.
The result of $(date) is not executed.
Two plus two is calculated by $((2 + 2))
<<の代わりに<<-(末尾にハイフンが付きます)を使うと、Bashはヒアドキュメントの各行の先頭にある_タブ文字_を取り除きます。
これは、出力に影響を与えずに、スクリプトの中でヒアドキュメントの内容をインデントしたいときに便利です。
# 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
出力は、先頭のタブをすべて取り除いた状態で表示されます:
This line has 1 leading tab.
This line has a leading tab and some spaces.
This line 2 leading tabs.
著者はこの使い方をあまりおすすめしていません。 スクリプトが読みやすくなることはありますが、
よくある使い方としては、ヘルプのテキストを表示することがあります:
#!/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
ヒアドキュメントと同じように、_ヒアストリング_もコマンドに入力を渡します。
ただし、ヒアドキュメントがテキストのブロックとして渡されるのに対し、ヒアストリングは1つの文字列として渡されます。
ヒアストリングでは<<< "text"という構文を使います。
tr 'a-z' 'A-Z' <<< "upper case this string"
出力:
UPPER CASE THIS STRING
ヒアドキュメントと違って、終了の区切り文字は必要ありません。
ヒアストリングの代わりにパイプを使うこともできます:
echo "upper case this string" | tr 'a-z' 'A-Z'
では、なぜヒアストリングを使うのでしょうか?
長い時間のかかる計算の出力として文字列を得て、その結果を2つの別々のコマンドに渡したい場合を考えてみましょう。 パイプを使うと、その計算を2回実行しなければなりません:
some_long_running_calculation | first_command
some_long_running_calculation | second_command
より効率的な方法は、その計算の出力を(コマンド置換を使って)変数に保存し、ヒアストリングを使って後続の2つのコマンドに入力を渡すことです:
result=$( some_long_running_calculation )
first_command <<< "$result"
second_command <<< "$result"
この例を実際の場面に当てはめたものが、次のものです:
# 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
出力リダイレクトの位置に注目してください。
whileループからの出力はすべて、ファイルdata.csvに追記されます。
これらはリダイレクトの一種にすぎないので、ほかのリダイレクト操作と組み合わせることができます:
cat <<< END_OF_TEXT > output.txt
This is my important text.
END_OF_TEXT
awk '...' <<< "$my_var" >> result.csv
ヒアドキュメント(「heredoc」)は、Bashスクリプトで複数行の入力を扱うための、柔軟で便利な方法です。 テキストやデータをスクリプトの中に直接埋め込む手間を減らし、スクリプトをより自己完結的で読みやすいものにしてくれます。
ヒアストリングはヒアドキュメントに似ていますが、よりシンプルで動的な構文を提供します。