以下で説明するbashコードが何をしようとしているのか、特にその[-z $M ]
部分を理解しようとしています。ここで、M は値を持つ変数です
if [ -z $M ] ; then
can not find module directory
exit 1
man test
Enter分かりますか:
-z STRING
the length of STRING is zero
あなたのスクリプトは、$M
長さ== 0の場合、ステータスコードで終了します1
他の人が言ったように、test
コマンド(別名[
)を使用して、文字列が空白かどうかを確認しています。少なくとも、それがやろうとしていることです。文字列 ( $M
) は二重引用符で囲まれていないため、実際には少し異なることを行っています。二重引用符がない場合、 の値は$M
置換後に単語分割とワイルドカード展開が行われるため、(-z
演算子が処理する) 単純な文字列として扱われない可能性があり、予期しない結果が生じる可能性があります。いくつかの可能性を見てみましょう。
$M
のない単一の単語 (非空白) である場合、すべてが期待どおりに機能します。*
?
の値が$M
長さ 0 (空白) の場合、テスト コマンドは 1 つの引数 ( -z
) のみを認識します。test に引数が 1 つしか与えられていない場合、空白かどうかを単純にテストします。空白でないため、true と評価されます。
この場合、これはたまたま期待される結果ですが、これはまったくの偶然によるものであり、他の多くの演算子では正しい結果にはなりません。たとえば、[ -n $M ]
( $M
*non*blank で[ -e $M ]
あるかどうかをテストする必要があるように見えます)、(ファイル/ディレクトリの名前であるかどうかをテストする必要があるように見えます) などは、空白$M
の場合はすべて true と評価されます。$M
$M
完全に空白で構成されている (ただし空ではない) 場合は、それを確認する前に削除され、truetest
とtest
評価されます (前のケースを参照)。これは、スクリプト作成者が念頭に置いていたものかもしれませんし、そうでないかもしれません。の値に$M
複数の単語がある場合test
、式 (の一部) として評価しようとします。それはおそらく有効な式ではないでしょう。その場合test
、エラーが出力され、false が返されます (これは正しい... 一種です)。
一方、それが有効な式である場合... たとえば、M='= -z
;があったとします。スクリプト作成者が考えていたものではなく、true になるtest
式を評価します。-z = -z
の値にワイルドカードが含まれている場合、シェルはワイルドカードをファイルと照合して、一致のリストを$M
渡します。test
それらを式として評価しようとします (前のケースを参照)。おそらくエラーが発生し、false が返されます (これも正しいことです)。
nullglob シェル オプションを設定していて、ワイルドカードがどのファイルとも一致しない場合、シェルはそれを null に置き換え、スクリプトは "u*n*m*a*t*c *h*e*d" は空の文字列でした。
ここでの教訓: スクリプトを奇妙で予期しない方法で動作させたくない場合は、変数参照を二重引用符で囲んでください。
これ[
は実際には標準の Unix コマンドです (おそらく Bash で内部的に実装されていますが、使用しているシェルに関係なく使用できます)。これはコマンドのエイリアスであるtest
ため、手動入力は と入力して見つけることができますman test
。そのマニュアル ページのオンライン コピーを次に示します。
として呼び出された場合[
、は通常、見栄えを良くするためにtest
最後の引数が であると想定するため、は と同等です。]
[ -z $M ]
test -z $M
この場合、次の-z
引数test
が長さゼロの文字列である場合、引数は true を返します。したがって、スクリプトのさらに上で定義された variable$M
は、有効な値についてテストできます。
variable の内容がM
空の文字列かどうかをチェックします。