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


23

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

while [ 0 ]; do
    echo "hello"
done

回答:


33

シェル内の単一の角括弧はtest(別個のコマンドまたはシェル組み込みの)の同義語であるため[ 0 ]、と同じことを意味しtest 0ます。testあなたはそのマンページで読むことができるように、比較を行い、ファイルの属性をテストするためのものです。比較、ファイルテスト、または実行可能な他の操作のように見える式が与えられない場合、代わりに引数が存在し、空でない文字列があるかどうかをテストします。0またはどちらも1テストに本当に適切な入力ではありません。空でない文字列のテストは単に成功し、whileループは永久にループします。

代わりに試してみてください

while false; do
  echo "hello"
done

おそらく交換falsetrue。または多分あなたが望むのは使用することです(( ))

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

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


1
Re:「比較、ファイルテスト、または他の操作のように見える式が与えられない場合、単に成功します」:それを置くのに良い方法だとは思わない 結局、[ ](引数なしで)および[ "" ](単一の空の引数で)成功しません
ruakh

3
@ruakhが説明するように、このステートメントは間違っています。比較、ファイルテスト、または実行可能な他の操作のいずれかのような式が指定されていない場合、単に成功します。 引数が空の文字列でない場合、テストに任意の単一の引数(角括弧内の任意の単一の引数)がTRUEであると考えられる、との両方0とは1空の文字列ではありません。新しいシェルプログラマーは、多くの場合、if [ 1=2 ]代わりに書いてif [ 1 = 2 ]、前者が常に真実である理由を疑問に思います。これは、単一の引数であり、空の文字列ではないため、真実です。
イアンD.アレン

良い点、私は修正を加えました。
wingedsubmariner

10

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

[ A ]
[ "XYZ" ]
[ 0 ]

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

[ ]
[ "" ]

論理的に真と評価される非空白引数があります。これにより、次のようなことができます。

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

この変数UNDER_NUCLEAR_ATTACKは、真を示すために空白以外の値に設定されるか、偽を示すために設定されていないか空です。

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

[ ! 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文字列を含む十進整数のようなその表情は、彼らは番号が比較され、そして場合Aよりも大きいBループを実行、。したがって、それUNDER_NUCLEAR_ATTACKは空白または非空白の文字列型ブール値ではなく、実際には0(false)または他の値(true)である数値ブール値であるとします。その場合、次のようなテストを作成します。

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

-1

if / thenコンストラクトは、コマンドのリストの終了ステータスが0であるかどうかをテストし(0はUNIXの慣例により「成功」を意味するため)、1つ以上のコマンドを実行します。

つまり、ゼロのテスト結果を返しています。

http://www.tldp.org/LDP/abs/html/testconstructs.html


5
はい、しかしあなたが考えるように思われる理由のためではない。場合[(除く一つだけの引数を取得し]、それがある場合、引数が空でない場合、それは状況ゼロで終了し、ゼロ以外に、もちろん、)。したがって、たとえば、[ 1 ]の終了コードも返します0
ケビン

-1

0の値はwhileループに対してtrueと見なされるため、whileループの条件はtrueであり、無限ループを示すために連続しています。0を1に置き換えるとtrueになります。条件の間に書き込む整数はすべてtrueを返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.