使用不等于运算符进行字符串比较

mun*_*ish 165 shell shell-script

我试图检查PHONE_TYPE变量是否包含三个有效值之一。

if [ "$PHONE_TYPE" != "NORTEL" ] || [ "$PHONE_TYPE" != "NEC" ] ||
   [ "$PHONE_TYPE" != "CISCO" ]
then
    echo "Phone type must be nortel,cisco or nec"
    exit
fi
Run Code Online (Sandbox Code Playgroud)

上面的代码对我不起作用,所以我尝试了这个:

if [ "$PHONE_TYPE" == "NORTEL" ] || [ "$PHONE_TYPE" == "NEC" ] ||
   [ "$PHONE_TYPE" == "CISCO" ]
then
    :        # do nothing
else
    echo "Phone type must be nortel,cisco or nec"
    exit
fi
Run Code Online (Sandbox Code Playgroud)

这种类型的任务有更干净的方法吗?

Nil*_*ner 237

我猜你正在寻找:

if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] &&
   [ "$PHONE_TYPE" != "CISCO" ]
Run Code Online (Sandbox Code Playgroud)

这些等价物的规则称为德摩根定律,在您的情况下意味着:

not(A || B || C) => not(A) && not(B) && not (C)
Run Code Online (Sandbox Code Playgroud)

注意布尔运算符 or 和 and 的变化。

而你试图做:

not(A || B || C) => not(A) || not(B) || not(C)
Run Code Online (Sandbox Code Playgroud)

这显然不起作用。


小智 51

一个更短的方法是:

if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO)$ ]]; then 
  echo "Phone type must be nortel, cisco or nec."
fi
Run Code Online (Sandbox Code Playgroud)
  • ^ – 匹配行首的开始
  • $ – 匹配行尾
  • =~ - Bash 内置的正则表达式比较运算符

  • 我认为应该是`if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO)$ ]]; 然后` (4认同)
  • 这个问题没有提到 bash,事实上,在标签和问题中都故意只提到“shell”脚本。这个答案在 POSIX 环境中会失败。 (3认同)

Run*_*ium 16

很好的答案,以及宝贵的教训 ;) 只想补充一个注释。

选择使用哪种类型的测试在很大程度上取决于代码、结构、环境等。

另一种方法是使用 switch 或case语句,如下所示:

case "$PHONE_TYPE" in
"NORTEL"|"NEC"|"CISCO")
    echo "OK"
    ;;
*)
    echo "Phone type must be nortel,cisco or nec"
    ;;
esac
Run Code Online (Sandbox Code Playgroud)

作为第二个注意事项,您应该小心使用大写的变量名。这是为了防止系统引入的变量之间发生冲突,几乎总是大写。因此$phone_type而不是$PHONE_TYPE.

虽然那个是安全的,但如果你习惯使用全部大写,有一天你可能会说IFS="boo",你处于一个受伤的世界。

它还将使您更容易发现哪个是什么。

不是必须,但会强烈考虑。


它也可能是一个很好的函数候选者。这主要使代码更易于阅读和维护。例如:

valid_phone_type()
{
    case "$1" in
    "NORTEL"|"NEC")
        return 0;;
    *)
        echo "Model $1 is not supported"
        return 1;;
    esac
}

if ! valid_phone_type "$phone_type"; then
    echo "Bye."
    exit 1
fi
Run Code Online (Sandbox Code Playgroud)


jll*_*gre 13

您应该使用 AND 而不是 OR。

if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] && [ "$PHONE_TYPE" != "CISCO" ]
then
Run Code Online (Sandbox Code Playgroud)

或者

if [ "$PHONE_TYPE" != "NORTEL" -a "$PHONE_TYPE" != "NEC" -a "$PHONE_TYPE" != "CISCO" ]
then
Run Code Online (Sandbox Code Playgroud)