正常に動作する次のスクリプトがあります。
!/bin/bash
a=12
while [ $a -gt 10 ]
do
echo "$a"
a=$(($a-1))
done
echo "done"
「do」の上に「echo something」という行を追加すると、その行に構文エラーが表示されるはずです。のようだ [ $a -gt 10 ]
はバイパスされ、無限ループになります。どうしてそうなるのでしょうか?
から bashマニュアル :
while
while
コマンドの構文は次のとおりです。whiletest-commands; doconsequent-commands; doneconsequent-commands
の終了ステータスがゼロである限り、test-commands
を実行します。戻りステータスは、consequent-commands
で最後に実行されたコマンドの終了ステータス、または何も実行されなかった場合はゼロです。
注:test-commands
、plural。テストでは複数のコマンドを使用できるため、これは完全に有効なループであり、コマンドのリスト[ $a -gt 10 ]; echo "$a"
をテストとして使用します。
while [ $a -gt 10 ]
echo "$a"
do
a=$(($a-1))
done
コマンド[ $a -gt 10 ]
は失敗する場合と失敗しない場合がありますが、echo
は(ほとんど)常に成功します(テキストを書き込めなかったか、その他のエラーが発生した場合を除く)。したがって、finalテストコマンドの終了ステータスは常に成功し、ループは常に実行されます。
man bash
から:
一方、リスト-1;リスト2を実行します。終わった
whileコマンドはリストを継続的に実行しますlist-2
最後のコマンドがリストにある限りlist-1
ゼロの終了ステータスを返します。
これは、list
に複数のコマンドが含まれている可能性があることを意味します(ほとんどがセミコロンまたは改行で区切られています)。
したがって、これは完全にうまく機能します:
#!/bin/bash
a=12
while
echo something
echo "a before test = $a"
[ a -gt 10 ]
do
echo "a after test = $a"
a=$(($a-1))
done
echo "done"
do
の前の最後のコマンドがエコーである場合、do receiveが常に真(0)であるという終了コードがあり、ループは無限になります。
ここで他の答えが意味するが明示的には言っていないのは、[
は組み込みcommandであり、while
ステートメントの構文部分ではありません。
入力してみてくださいhelp [
コマンドラインで:
[
:[
引数...]
条件式を評価します。これは組み込みの「テスト」の同義語ですが、最後の引数は
リテラルであること]
、オープニングと一致する[
。
したがって、スクリプトはexactly as:
!/bin/bash
a=12
while test $a -gt 10
do
echo "$a"
a=$(($a-1))
done
echo "done"
どちらに変更するか:
!/bin/bash
a=12
while test $a -gt 10; echo something
do
echo "$a"
a=$(($a-1))
done
echo "done"
これの極端な例として、/ usr/bin/tzselectは通常、メインステートメントのwhile
とdo
の間に、caseステートメントとコマンド置換を含む約70行のコードがあります。 、およびdo
とdone
の間の1行。
(他の回答を補足するメモとして)。
条件リストでいくつかのコマンドを使用することは、Cのdo { blah; blah; } while (condition)
に似たループを実装するためによく使用されます。つまり、ループの最後で条件がチェックされ、ループ内のコードが少なくとも1回実行されます。
sh
では、次のようにします。
while
blah
blah
condition
do
continue # or :
done
他のアプローチも可能ですが:
while true; do
blah
blah
condition || break
done
または:
continue=true
while "$continue"; do
blah
blah
condition || continue=false
done
end=false
until "$end"; do
blah
blah
condition || end=true
done