簡単なスクリプトを試してみたいです。
flag=false
while !$flag
do
read x
if [ "$x" -eq "true" ]
then
flag=true
fi
echo "${x} : ${flag}"
done
ただし、実行時に入力するとandがtrue
表示されますが、ループは終了しません。スクリプトにどのような問題がありますか?ブール変数を正しく反転する方法は?x="true"
flag="true"
答え1
スクリプトには2つのエラーがあります。 1つ目は、!
との間にスペースが必要です$flag
。それ以外の場合、シェルはというコマンドを探します!$flag
。 2番目のエラーは-eq
整数比較のためのものですが、文字列に使用しています。シェルによってはエラーメッセージが表示され、条件が真になることができないか、整数以外のすべての値がゼロとして処理されるため、ループは永久に続行されます。を含む文字列を入力すると、[ "$x" -eq "true" ]
ループはfalse
次の数字で終了します。 0.
これは正しいですが、! $flag
文字列をコマンドとして扱うことはお勧めできません。動作しますが、スクリプトの変更に非常に敏感です。またはそれ以外のもので$flag
ないことを確認する必要があるからです。ここでは、以下のテストのように文字列比較を使用する方が良いです。true
false
flag=false
while [ "$flag" != "true" ]
do
read x
if [ "$x" = "true" ]
then
flag=true
fi
echo "${x} : ${flag}"
done
あなたが求める論理を表現するより良い方法があります。たとえば、無限ループを作成し、終了条件が検出された場合はこれを中止できます。
while true; do
read -r x
if [ "$x" = "true" ]; then break; fi
echo "$x: false"
done
答え2
Bashにはブール変数はありませんが、算術評価を使用してこれをエミュレートするのは非常に簡単です。
flag= # False
flag=0 # False
flag=1 # True (actually any integer number != 0 will do, but see remark below about toggling)
flag="some string" # Maybe False (make sure that the string isn't interpreted as a number)
if ((flag)) # Test for True
then
: # do something
fi
if ! ((flag)) # Test for False
then
: # do something
fi
flag=$((1-flag)) # Toggle flag (only works when flag is either empty or unset, 0, 1, or a string which doesn't represent a number)
これはkshでも動作します。すべてのPOSIX互換シェルで動作しても驚くことはありません。しかし、まだ標準を確認していません。
答え3
変数に0または1が含まれると確信している場合は、ビットXOR等号演算子を使用して2つの値を切り替えることができます。
$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0
答え4
シェルにはブール変数の概念はありません。
シェル変数は(文字列)のみであり、text
場合によってはテキストを整数(1
、0xa
など010
)として解釈することができます。
したがって、aはflag=true
シェルに対して真または偽を意味しません。
ひも
できることは、文字列比較[ "$flag" == "true" ]
または一部のコマンドで変数の内容を使用して確認することです。その結果、コマンドで実行(名前付き実行ファイルと名前付き実行ファイルのtrue
両方があるため)し、そのコマンドの終了コードが0(成功)であることを確認するのと同じです。true
false
$flag; if [ "$?" -eq 0 ]; then ... fi
またはより短く:
if "$flag"; then ... fi
変数の内容がコマンドとして使用されている場合、次のように2つの間にスペース()がある場合は、aを!
使用してコマンドの終了状態を無効にできます。! cmd
if ! "$flag"; then ... fi
スクリプトは次のように変更する必要があります。
flag=false
while ! "$flag"
do
read x
if [ "$x" == "true" ]
then
flag=true
fi
echo "${x} : ${flag}"
done
整数
数字と算術拡張。
この場合の終了コード$((0))
はで1
、終了コードは$((1))
です0
。
bash、ksh、およびzshでは、a内で算術を実行できます(((..))
始めがないことに注意してください)。$
flag=0; if ((flag)); then ... fi
このコードの移植可能なバージョンはより複雑です。
flag=0; if [ "$((flag))" -eq 0 ]; then ... fi # test for a number
flag=0; if [ "$((flag))" == 0 ]; then ... fi # test for the string "0"
bash/ksh/zsh では、次のことができます。
flag=0
while ((!flag))
do
read x
[ "$x" == "true" ] && flag=1
echo "${x} : ${flag}"
done
または
「ブール変数を反転」できます(数値が含まれている場合)。
((flag=!flag))
そうだろう変化flag
または0
価値1
。
ノート:エラーがないか確認してください。https://www.shellcheck.net/多くの場合、問題をコードを発行する前に問題を見つけるのに十分です。