Bash脚本:布尔变量不能正常工作

时间:2011-11-12 23:07:18

标签: 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时,它不应该在最后一个if但是它会进入。

我不明白为什么会这样。

有人知道吗?

非常感谢。

4 个答案:

答案 0 :(得分:7)

那是因为你在|之后设置了真值,即在子shell中。子shell中的变量值不会传播回父shell。摆脱子shell:

while read line
do
    ...
done <<< "$tmp"

答案 1 :(得分:3)

问题不在于布尔值,而是while循环在管道中,因此在子shell中执行。更改子shell中的DEVICE_FOUND对主shell中的DEVICE_FOUND没有影响,它只是保持为false。如果你正在使用bash(即如果脚本开头的shebang是#!/bin/bash,而不是#!/bin/sh),有几种方法可以消除管道:

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 "ERROR: The device "$DEVICE_ID" is not connected"
    exit
fi

答案 2 :(得分:1)

Bash缺少布尔变量。因此,DEVICE_FOUND=false会将字符串false分配给$DEVICE_FOUND

你可以通过使用“空变量”条件作为你的“假”和“非空变量”作为你的“真”(或者如果你想要的话,反之亦然)来获得通常的布尔标志功能,或以其他方式检查任意值。例如:

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

答案 3 :(得分:0)

bash(以及任何符合POSIX的shell)中没有布尔类型。实际有效的是,您正在运行true(退出成功状态,不一定是0)或false(退出失败0语句中的em> status,不一定不是if外部命令。如果第一个列表的计算结果为if,则0语句将执行第二个列表。您可能遇到过这样的系统:truefalse命令都不可用,或者它们的工作方式与预期不同。使用“整数”值(所有值都是内部字符串)或空/非空字符串值。

另外请注意:

adb devices | tail -n +2 | awk '{print $1}' | while read …
do
  …
done