終了コードで終了するまでコマンドを繰り返したかったので、0
次のことを試しました。
$ while/until $?; do $command; done
しかし、 and not のuntil/while
ようなブール値のみを許可するようです。true/false
0/1
私は似たようなものや何かを逃しましたか[[ ]]
?
答え1
while
キーワードuntil
に注文する彼らの主張で。コマンドが「成功」を示すゼロ終了状態を返すと、while
ループ本文内のコマンドが実行されuntil
ます。いいえループ本体内でコマンドを実行します。
while
あなたのコードは、and until
with $?
(最も最近のコマンドの終了ステータス)をコマンドとして使用しているようです。名前が整数のコマンドがシステムに存在しない場合は機能しません。何会議タスクはtest
コマンドを使用してと比較することです0
。
until test "$?" -eq 0; do some-command; done
または略語を使用test
して
until [ "$?" -eq 0 ]; do some-command; done
これで問題は、明らかに$?
ループに入るとゼロになり、ループが一度実行されるのを防ぐことです。コマンド自体が終了状態を or に直接提供するようにする方がwhile
合理的ですuntil
(たとえば、ループの前に呼び出してゼロ以外の値に初期化したい場合以外は奇妙に$?
見えます)。false
標準のPOSIXを使用する(Bourneではありませんが、今は重要ではありません)シェル構文:
while ! some-command; do continue; done
または(BourneとPOSIX)、
until some-command; do continue; done
両方のコマンドは、some-command
ゼロ終了ステータス(「成功」)が返されるまで実行されます。繰り返しごとに、continue
ループ本体の内部のキーワードを実行します。実行はcontinue
ループの次の反復に即座にジャンプしますが、これを使用して、たとえば、sleep 5
各反復で短い遅延が発生したり、何も実行しないよう:
にすることができます。
別の変形は無限コマンドが成功すると終了するループ:
while true; do some-command && break; done
または、より冗長で読みやすくするためにスペースを追加するには
while true; do
if some-command; then
break
fi
done
あなたが本当に唯一の時間必要$?
次のように、一定期間にわたって値を追跡する必要がある場合に使用されます。
somefunction () {
grep -q 'pattern' file
ret=$?
if [ "$ret" -ne 0 ]; then
printf 'grep failed with exit code %s\n' "$ret"
fi >&2
return "$ret"
}
上記のコードでは、$?
テストによって終了ステータスがリセットされ、[ "$ret" -ne 0 ]
それを別の変数に保存しないと、その値を印刷したり関数から返すことはできません。
もう一つの指摘すべき点は、あなたが使用しているようです。ひも、$command
(引用符なし)をコマンドとして使用します。これは〜になりますはるかに良い変数に格納されたコマンドを実行するには、配列を使用します。
thecommand=( awk -F ',' 'BEGIN { "uptime" | getline; split($4,a,": "); if (a[2] > 5) exit 1 }' )
while ! "${thecommand[@]}"; do sleep 5; done
(このサンプルコードは、1分平均システム負荷が5未満になるまで5秒ごとに待機します。)
配列を使用して拡張を参照することで、"${thecommand[@]}"
シェルが文字列を単語に分割し、各単語にファイル名ワイルドカードを適用する方法を心配することなくコマンドを実行できます。
また、見ることができます変数に保存されたコマンドをどのように実行できますか?あなたの質問に関する追加情報です。
答え2
次のことができます。
false; while [[ $? -ne 0 ]]; do
command
done
ここでは、false
最初にゼロ以外の値に設定され、$?
ループを少なくとも1回実行できます。指定されたコマンドは、ゼロ終了状態で終了するまでループで実行されます。