ヒアドキュメントとは
複数行の文字列を簡潔に記述するための機能です。
これを
echo 'hoge'
echo 'fuga'
echo 'piyo'
こんな風に記述できます
cat << EOS
hoge
fuga
piyo
EOS
ヒアドキュメントはシェルスクリプトの中にちょっとした別のスクリプトを埋め込むときに便利です。
数行のスクリプトのためにわざわざファイルを作る必要がなくなり、見通しがよくなります。
# ちょっとしたスクリプトを動かすのに便利
# 例) oracleDBのテーブル一覧を出力する
sqlplus -S user/pass@sid << EOS
set pagesize 0
set feedback off
select table_name from tabs
order by table_name;
EOS
要点
ヒアドキュメントを理解するうえで重要なのは、ヒアドキュメントは標準入力として扱われる、ということです。
文字列リテラルでないことに注意してください。
これを把握していれば、最初の例でcat
にヒアドキュメントを渡していた理由がわかるかと思います。
cat
はファイルを省略した場合に標準入力から読むため、ヒアドキュメントの内容が標準出力に出ることになります。
逆に下記のようにecho
に渡しても内容が標準出力に出ることはありません。echo
は標準入力から読まないし、
ヒアドキュメントはリテラルではないからです。
# 改行が出力されて終わり
echo << EOS
hoge
fuga
EOS
文法
コマンドに<< EOS
が渡されると次の行からEOSが単独で現れる行までの間が
ヒアドキュメントの内容になります。
言い換えれば、コマンドそのものが記載された行に、コマンドの振る舞いを指定し、
そこで標準入力として与える内容を次の行から記載することになります。
EOS
の部分は任意の文字を使うことができます。HOGE
でも_DOC_
でも問題ありません。
「EOSが単独で現れる行」というのは空白やタブなど、一切のほかの文字も含んではいけません。
「次の行から」というのもポイントです。
つまりは以下のようにも書けます。
# ヒアドキュメントの内容とmyfile.txtの内容を連結してconcat.txtに書き込む
cat - << EOS myfile.txt > concat.txt
hoge
fuga
EOS
なおここで、catの直後-
は、catの仕様として、ファイル名を指定すると標準入力から読み込まなくなるため、
明示的に-
を指定して、標準入力として渡したい箇所を指定する必要があります。
変数展開・コマンド置換
ヒアドキュメントの中でも""
で括った文字列リテラルと同様、
変数展開やコマンド置換が行われます。
つまり$MY_VAR
や$(date)
と書くといつもと同じように展開されます。
これを抑止する(=''
で括ったときのように扱う)にはEOS
の部分を下記のようにクォートします。
cat << 'EOS'
$MY_VAR と書いても展開されない
EOS
行頭のタブを取り除く
ヒアドキュメントは便利ですが、インデントできないのが難点です。
EOSをインデントしてしまうとヒアドキュメントの終わりとして認識してくれませんし、
ヒアドキュメントの内容にインデントがそのまま反映されてしまいます。
この問題を解決するための機能が用意されていて、<<
を<<-
に書き換えるだけで
使用できます。<<-
でヒアドキュメントを書くと、行頭のタブを無視してくれます。
ただし、タブといっているのはハードタブのみでスペースは相変わらず取り除いてくれません。
(たぶんヒアドキュメント中でインデントするときのためにこうしていると思うのですが・・・)
# >--- はハードタブだと思って読んでください
cat <<- EOS
>--- hoge
>--- fuga
>---EOS
上記の例は
hoge
fuga
と表示されます。
変数に代入する
ヒアドキュメントは標準入力なので、変数に入れるにはちょっとした細工が必要です。
以下のようにすれば変数に代入することができます。
HOGE=$(cat << EOS
hoge
fuga
EOS
)
# もしくは
HOGE=`cat << EOS
hoge
fuga
EOS
`