RM-BLOG

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

【UNIX】ヒアドキュメント(ここからここまでまとめて実行よろしく)の書き方

UNIX系で内部コマンドがあるようなものに対して
「ここからここまでよろしく」という”まとめ指示”を記述する方法。
ラベルとかいう制御の方法に近いのかな。よくしらないが。

2019/01/29追記

これ「ヒアドキュメント」という記法らしいです(無知でしたw)

たとえばsqlplusでまとめて指示したいときは↓みたいに書く。

sqlplus -s /nolog << MATOMETE
connect SCOTT/TIGER@TESTDB;
select sysdate from dual;
exit;
MATOMETE

この記述では、
”sqlplusにサイレントモードとnologでとりあえす接続して「MATOMETE」ってかいてあるところまで一通り連続して処理して”
という指示を出している。
sqlplusに接続した後は、
SCOTT/TIGERでTESTDBに接続し(connect SCOTT/TIGER@TESTDB;)
sysdate発行して(select sysdate from dual;)
DBから出る。(exit;)
簡単のためsysdate発行だけにしているがここには当然他SQL文を書くことができる。

 
sqlplusでいえば、shスクリプトから呼び出すとき、
外だしのsqlファイルを
sqlplus SCOTT/TIGER@TESTDB @./SYSDATE.sql
みたいに呼び出すよりは、
shスクリプト内に直接sqlplusのコマンドを書けるので、
スクリプトファイルが「呼び出し元のshファイル」だけになり、管理が楽になる。
その分一つのスクリプトファイル内にsqlUNIXコマンドも同居することになるので、
当然コードは長くなりがち。
呼び出すsqlが長いとか、さらにそこから別のsqlを呼び出してるとか、
そういうものであればこの記述は適さないように思う。
使い分けが重要だろう。


ちなみに同じことはftpでもできる。
MS-DOS用のftpでは-s:[filename]オプションにより、
filenameに指定した外だしのファイルにftpのコマンドを列挙することができるが、
それと同じようなことをこの”まとめ指示”で行うことができる。

ftp -n << FTPMATOMETE
user testuser tesuser
cd /home/testuser/
bin
get test.txt
bye
FTPMATOMETE

この記述では、
ftpでとりあえず接続して「FTPMATOME」ってかいてあるところまで一通り連続して処理して”
となる。
ftpで接続した後は、
testuser/testuserでログインして(user testuser tesuser)
/home/testuserに移動して(cd /home/testuser/)
バイナリモードに変更した後(bin)
test.txtをゲット(取得)し(get test.txt)
ftpから出る。(bye)


また、これら一連の処理の結果をリダイレクトする場合は

sqlplus -s /nolog << MATOMETE  > ./redirect.txt
connect SCOTT/TIGER@TESTDB;
select sysdate from dual;
exit;
MATOMETE

とする。
これは「sqlplus -s /nolog << MATOMETE」というコマンド(実態はその下に書いてある一連のコマンド群だがそれの指示を出す大元を指定)を「./redirect.txt」に出力しろ、
という命令になる。

これの応用(?)で、標準エラー出力を含め全てを「闇に葬る」やり方だと

sqlplus -s /nolog << MATOMETE  > /dev/null 2>&1
connect SCOTT/TIGER@TESTDB;
select sysdate from dual;
exit;
MATOMETE

という感じになる。
なんだか<や>が増えてごちゃごちゃしてしまうが…


同じようなことは標準入力から値を受け取る自作のshスクリプトでもできる。
例えばshスクリプトが↓になってるとして
◆test_read.sh

#!/bin/sh

read VAR
echo "Your Input is $VAR"

これを別のshスクリプトから呼び出すような場合、ここに書いた方法で

sh ./test_read.sh << MATOMETE
aaa
MATOMETE

ってやれば、Your Input is aaaという標準出力結果が得られる。
この「aaa」って部分は当然コマンドではないけど、
標準入力として「MATOMETE」って部分に書いたところまでを「sh ./test_read.sh」に渡せ、
という指示として生きてくる。