Shellの[[ ... ]]と[ ... ]の違い
主にbashとかkshの話
404 Blog Not Found:perl - glob,readdir, and regexpを読んで、昔Shellのグロブ展開でハマったことを思い出したので適当に書いておく。
Shellスクリプト等で複合コマンドの[[ ... ]]
とtest
コマンドと同等の[ ... ]
をきちんと使い分けている人は意外と少ないのでは無いかと思う。[[ ... ]]も[ ... ]の違いはグロブ展開するかしないかの違いと言ってよいだろう。
変数$hogeが文字列"hoge"から始まる文字か評価したい場合を考えてみる。
if [ $hoge = hoge* ];then # .... fi # or if [ $hoge = "hoge*" ];then #.... fi
などとやって怒られた経験のある人はたくさんいると思う。なぜダメかというと、[ ... ]はtest
コマンドと同等だからだ。上記を書き換えると
if test $hoge = hoge*;then #... fi # or if test $hoge = "hoge*";then #... fi
となる。
test
コマンドは立派なコマンドだ。*
,?
などのパターンマッチ文字があればパス名展開しようと試みる。また、引用符で囲まれていれば単なる文字列として扱われる。
よって、1番目はカレント・ディレクトリにhogeから始まるファイルがあれば、そのファイル名に展開されてしまう。複数ある場合はtest
コマンドが評価する時にはtest $hoge = hogefoo hogebar
となり、構文エラーとなってしまう。
2番目は文字列と扱われるため、$hogeが文字列hoge*
であるかどうかの評価となる。
そんな場合のために[[ ... ]]がある。こちらはコマンドというよりかは構文に近いものがあり、単語分割やパス名展開を行わず、パターンマッチが可能になっている。
if [[ $hoge = hoge* ]];then # .... fi