testコマンド、知ってますか
シェルスクリプトで重要な役割を果たすのがtestコマンドです。
sample1.sh
if[$# -eq 1 ];then
echo'an argument is set'fi
といった感じで使います。
え?どこにtest
が使われているんだって?[]
がtest
コマンドのシンタックスシュガーです。[
の直後、]
の直前には必ず半角スペースを入れましょう(初心者がハマりがちな罠)
オプション色々
test
コマンドには様々なオプションがあります。
- 引数をオプションの前後に取るもの
-eq
,-ne
,-gt
,-ge
,-lt
,-le
: 数値比較(等しい、等しくない、大きい、以上、小さい、以下)=
,!=
: 文字列比較(等しい、等しくない)
- 引数をオプションの後ろにのみ取るもの
-n
,-z
: 文字列長(0ではない、0である)-e
,-f
,-d
など: ファイル確認(存在する, 通常ファイルである, ディレクトリである)-v
: 変数が定義されている
sample2.sh
hoge='sample2.sh'if[$hoge='sample2.sh'];then
echo"I am $hoge"# I am sample2.shと出力
end
if[-e$hoge];then
echo"$hoge exists!"# sample2.sh exists! と出力
end
変数の展開
さて、シェルには変数の展開という機能があります。
さきほどのsample2.shの中で、echo "I am $hoge"
という命令で I am sample2.sh
と出力していた機能です。
この機能、意識しないとハマります
sample3.sh
if[$# -eq 1 ];then$arg1='yobaretayo'fi
if[-v$arg1];then
bundle exec ruby hoge.rb --opt$arg1else
bundle exec ruby hoge.rb
fi
hoge.rb
#require 'optimist'classHogedefinitialize@options=Optimist::optionsdoopt:opt,'Option',type: :string,required: falseendenddefrunecho@options[:opt]if@options[:opt]endend
というシェルプログラムを書きました。
hoge.rbは --optというオプションを受け取るか、引数なしで呼び出されます。
ところが、$ ./sample3.sh
というコマンドを実行すると、Error: option '--opt' needs a parameter.
というエラーになってしまうのです。
$arg1はsample3.shの引数がない場合には未定義なので、if [ -v $arg1 ];
はfalse(!=0)となり、bundle exec ruby hoge.rb
が呼ばれるはずです。
はて・・・?
正解はif [ -v arg1 ];
でした。
違いがわかりますか?
if [ -v $arg1 ];
は変数の展開が行われて if [ -v ];
と解釈されてしまい、true(=0)で扱われるのです。
シェルスクリプトでtestコマンドを利用する際は変数の展開を意識しないとハマるよ、というお話でした。
おわり