web-dev-qa-db-ja.com

なぜwhile [0]が無限ループに入るのですか?

以下のループの動作は、while [ 1 ]のループと同じです。どうしてこんなことに?

while [ 0 ]; do
    echo "hello"
done
23
user13107

シェルの単一の角括弧はtest(個別のコマンドまたはシェルの組み込み)の同義語であるため、[ 0 ]test 0と同じ意味です。 testは、マンページで確認できるように、ファイルの属性を比較およびテストするためのものです。比較、ファイルテスト、または実行できる他の操作のような式が指定されていない場合、代わりに、引数が存在し、空でない文字列であるかどうかをテストします。 01もテストに適切な入力ではありません。空でない文字列テストは単純に成功し、whileループは永久にループします。

代わりに試すこともできます

while false; do
  echo "hello"
done

falsetrueに置き換える可能性があります。あるいは、(( ))を使用することもできます:

while (( 0 )); do
  echo "hello"
done

これはほとんどの言語と同じように動作し、0は失敗/偽、1は成功/真を意味します。

33

ここで値0は数値定数としてではなく、文字列として機能します。これらのテストはすべて、正常終了ステータスを生成する効果が同等です。

[ A ]
[ "XYZ" ]
[ 0 ]

これらは、失敗した終了ステータスを生成します。

[ ]
[ "" ]

論理trueと評価される非空白の引数があります。これにより、次のようなことが可能になります。

if [ $UNDER_NUCLEAR_ATTACK ] ; then
  launch-missiles -a $DRY_RUN  # $DRY_RUN set to "-n" during testing
fi

変数UNDER_NUCLEAR_ATTACKは、trueを示すには空白以外の値に設定され、falseを示すには未設定または空です。

!演算子を適用して、ロジックを逆にすることができます。

[ ! a ]  # fails: a is nonblank so true; and not true is false.
[ ! ]    # succeeds: blank is false, not blank is true.

数値条件を評価するには、数値テスト演算子を使用する必要があります。

 while [ $A -gt $B ] ; do ...

ABに10進整数のように見える文字列が含まれている場合、それらは数値のように比較され、ABより大きい場合、ループが実行されます。したがって、UNDER_NUCLEAR_ATTACKが空白または非空白の文字列型のブール値ではなく、実際には0(false)またはその他の値(true)の数値ブール値であるとします。その場合、次のようにテストを記述します。

 if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...
10
Kaz