Bashスクリプト:ブール変数が正しく機能しない

私はBashスクリプトでブール変数を評価しようとしていますが、常にfalseを返します。

ここにコードです:

DEVICE_FOUND=false
tmp=`adb devices | tail -n+2 | awk '{print $1}'`

echo "$tmp" | while read line
do
    if [ "$DEVICE_ID" = "$line" ]
    then
        echo "Found a device"
        DEVICE_FOUND=true
    fi
done

if ! $DEVICE_FOUND
then
    echo "ERROR: The device "$DEVICE_ID" is not connected"
    exit
fi

「デバイスの発見」が実行されるかどうかにかかわらず、私は常にifステートメントに入ります。 DEVICE_FOUND = trueの場合は、最後には入りませんが、そうしてください。

私はなぜそれが分からないのですか?

誰も知っていますか?

どうもありがとうございました。

3

4 答え

これは、 | の後、つまりサブシェル内に真の値を設定しているためです。サブシェルからの変数値は、親シェルに伝播しません。サブシェルを取り除く:

while read line
do
    ...
done <<< "$tmp"
7
追加された
どうもありがとうございました!これは動作します!
追加された 著者 Jary,

問題はブール値ではなく、whileループがパイプラインにあるため、サブシェルで実行されます。サブシェルでDEVICE_FOUNDを変更しても、メインシェルのDEVICE_FOUNDには何の影響もなく、falseのままです。 bashを使用している場合(つまり、スクリプトの先頭にあるシボンが#!/ bin/sh ではなく#!/ bin/bash である場合)、パイプを排除するための2つの方法:

while read line
do
    if [ "$DEVICE_ID" = "$line" ]
    then
        echo "Found a device"
        DEVICE_FOUND=true
    fi
done < <(echo "$tmp")

または:

while read line
do
    if [ "$DEVICE_ID" = "$line" ]
    then
        echo "Found a device"
        DEVICE_FOUND=true
    fi
done <<<"$tmp"

しかし、この特別なケースでは、( $ DEVICE_ID に正規表現のメタキャラクタがない場合)より良い方法があります。

if echo "$tmp" | grep -q "^$DEVICE_ID\$"; then
    echo "Found a device"
else
    echo "ERRまたは: The device "$DEVICE_ID" is not connected"
    exit
fi
3
追加された

Bashにはブール変数がありません。したがって、 DEVICE_FOUND = false$ DEVICE_FOUND に文字列 false を割り当てます。

あなたはあなたの "偽"として "空変数"の条件を使用し、 "真"(またはあなたが望むならば反対)のように "空でない変数"を使用するか、あるいはそれ以外の任意の値をチェックすることによって通常のブールフラグ機能を得ることができます。例:

DEVICE_FOUND=""
tmp=`adb devices | tail -n+2 | awk '{print $1}'`

echo "$tmp" | while read line
do
    if [ "$DEVICE_ID" = "$line" ]
    then
        echo "Found a device"
        DEVICE_FOUND=true
    fi
done

if [ ! "$DEVICE_FOUND" ]
then
    echo "ERROR: The device "$DEVICE_ID" is not connected"
    exit
fi
1
追加された
truefalse はbash組み込み関数です。あなたのコードには元のバグと同じバグがあります。私の答えを見てください。
追加された 著者 choroba,
@choroba:そうではないとは言いませんでしたが、 DEVICE_FOUND = true は依然として文字列の割り当てです。あなたはそのバグについて正しいです。
追加された 著者 ata,
どうもありがとう。奇妙な、私はまだそのエラーを取得しています!
追加された 著者 Jary,
デバイスが見つかりましたエラー:デバイスHT91MLD00464が接続されていません
追加された 著者 Jary,

bash(およびPOSIX準拠のシェル)にはboolean型はありません。実質的には、 true0 でなく false ステータスで終了) if ステートメントに 0 ではない失敗ステータスで終了します。最初のリストが 0 と評価された場合、 if ステートメントは2番目のリストを実行します。 true または false のどちらのコマンドも使用できないシステムや、期待したものとは異なる動作をするシステムに遭遇した可能性があります。 「整数」の値(すべての値が内部的に文字列)または空の/空でない文字列の値を代わりに使用します。

副題として、これを考えてみましょう。

adb devices | tail -n +2 | awk '{print $1}' | while read …
do
  …
done
0
追加された
サブシェルはなぜこれが失敗するのか(+1)の可能性が高い説明ですが、私は私の答えをさらに参考にしておきます。
追加された 著者 PointedEars,