bashのヒアドキュメントを活用する

  • 228
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

ヒアドキュメントとは

複数行の文字列を簡潔に記述するための機能です。

これを

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

変数展開・コマンド置換

ヒアドキュメントの中でも""で括った文字列リテラルと同様、
変数展開やコマンド置換が行われます。

つまり$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
`