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
fihoge.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コマンドを利用する際は変数の展開を意識しないとハマるよ、というお話でした。
おわり