testコマンド、知ってますか
シェルスクリプトで重要な役割を果たすのがtestコマンドです。
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
: 変数が定義されている
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
と出力していた機能です。
この機能、意識しないとハマります
if [ $# -eq 1 ]; then
$arg1 = 'yobaretayo'
fi
if [ -v $arg1 ]; then
bundle exec ruby hoge.rb --opt $arg1
else
bundle exec ruby hoge.rb
fi
# require 'optimist'
class Hoge
def initialize
@options = Optimist::options do
opt :opt, 'Option', type: :string, required: false
end
end
def run
echo @options[:opt] if @options[:opt]
end
end
というシェルプログラムを書きました。
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コマンドを利用する際は変数の展開を意識しないとハマるよ、というお話でした。
おわり