Bashシェルスクリプトのヒアドキュメントとは一体何か?
はじめに
シェルスクリプトを書いていてよく利用する記法として「ヒアドキュメント」があります。
Wikipediaには「文字列リテラルをソースコード中に埋め込む方法のひとつ」という記載がありますが、
「文字列リテラル」という認識でいると echo
しようとして何も表示されないというミスをすることもあります。
検証環境
$ bash -version | head -n 1
GNU bash, バージョン 5.0.7(1)-release (x86_64-apple-darwin18.5.0)
ヒアドキュメントを使って文字列を出力する
文字列を出力したい場合、ヒアドキュメントを使って出力させる方法があります。
複数行にまたがるような長い文字列を出力したい場合に利用されることが多いです。
以下は cat
コマンドを利用してヒアドキュメントを出力させる例です。
$ cat <<EOF
Hello World!
My name is ${USER}.
EOF
実行結果は以下のようになります。
Hello World!
My name is genzouw.
ヒアドキュメントに埋め込まれた「変数」は展開されます。
echo
では出力できない
文字列を出力するというイメージからついつい echo
を使ってしまうことがありますが、これはNGです。
$ echo <<EOF
Hello World!
My name is ${USER}.
EOF
上記のコマンドを実行しても何も出力されません。
ヒアドキュメントとは一体何か?
本題にはいります。 cat
で表示できたことから「ファイル」または「標準入力」のいずれかの扱いになるかと思いますが、以下のようなPHPスクリプトを作成してヒアドキュメントを食わせてみます。
test.php
<?php
# test.php というファイル名で作成
echo '== ARGS', PHP_EOL;
var_dump($argv);
echo '== STDIN', PHP_EOL;
while (($line = fgets(STDIN)) !== false) {
echo $line;
}
大きく以下の2つの情報を出力しています。
- コマンドライン引数 (PHPでは
$argv
で取得できる。添字0
はスクリプト名が格納される。) - 標準入力 (PHPでは
STDIN
定数を使って標準入力を読み込むことができる。)
実行結果は以下のようになります。
$ php test.php <<EOF
Hello World!
My name is ${USER}.
EOF
== ARGS
array(1) {
[0]=>
string(8) "test.php"
}
== STDIN
Hello World!
My name is genzouw.
ヒアドキュメントは「標準入力」ですね。
パイプで渡しても同じ?
パイプで渡しても同じ結果を得られます。
先程の例は以下のコマンドと同様です。
# 改行を除外するために「バックスラッシュ」を2箇所埋め込んでいます
$ echo """\
Hello World!
My name is ${USER}.\
""" | php test.php
先程の echo
を使ってしまったケースは以下のような処理を実行したのと同じということになります。
# 改行を除外するために「バックスラッシュ」を2箇所埋め込んでいます
$ echo """\
Hello World!
My name is ${USER}.\
""" | echo
何も出力されないわけです。
ひとこと
Bashシェルスクリプトにおける ヒアドキュメント は「文字列リテラル」ではなく「標準入力」である!
ディスカッション
コメント一覧
まだ、コメントがありません