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


117

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

if [ "$PHONE_TYPE" != "NORTEL" ] || [ "$PHONE_TYPE" != "NEC" ] ||
   [ "$PHONE_TYPE" != "CISCO" ]
then
    echo "Phone type must be nortel,cisco or nec"
    exit
fi

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

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

有没有更清洁的方式来执行此类任务?

Answers:


162

我猜您在寻找:

if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] &&
   [ "$PHONE_TYPE" != "CISCO" ]

这些等价物的规则称为De Morgan定律,在您的情况下表示:

not(A || B || C) => not(A) && not(B) && not (C)

请注意布尔运算符or和and的更改。

而您尝试这样做:

not(A || B || C) => not(A) || not(B) || not(C)

这显然是行不通的。


28

一个更短的方法是:

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

2
我认为应该是if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO)$ ]]; then
Milan Simek

12

好的答案,非常宝贵的一课;)只想补充便笺。

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

另一种选择是使用如下所示的开关或case语句:

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

另外请注意,使用大写的变量名时要小心。这是为了防止系统引入的变量之间的冲突(几乎总是大写)。因此$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

9

您应该使用AND,而不是OR。

if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] && [ "$PHONE_TYPE" != "CISCO" ]
then

要么

if [ "$PHONE_TYPE" != "NORTEL" -a "$PHONE_TYPE" != "NEC" -a "$PHONE_TYPE" != "CISCO" ]
then

1

要纠正上述答案(因为我无法发表评论):

PHONE_TYPE="NORTEL"
if [[ $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO|SPACE TEL)$ ]]; then 
  echo "Phone type accepted."
else
  echo "Error! Phone type must be NORTEL, CISCO or NEC."
fi

请注意,您至少需要bash 4才能使用=〜
在bash 3中不起作用。

我在MS Windows 7上使用bash 4.3.46(可以正常工作)和bash 3.1.17(无法正常工作)进行了测试

=〜的LHS应该用引号引起来。在上方,PHONE_TYPE =“ SPACE TEL”也将匹配。


0

使用[[代替

if [[ "$PHONE_TYPE" != "NORTEL" ]] || [[ "$PHONE_TYPE" != "NEC" ]] || 
   [[ "$PHONE_TYPE" != "CISCO" ]]
then
echo "Phone type must be nortel,cisco or nec"
exit 1
fi

2
当然,这是错误的。[[vs [不利于逻辑关闭。
ilkkachu

0

只是基于@ 0x80解决方案的变体建议:

# define phone brand list
phoneBrandList=" NORTEL NEC CISCO" ## separator is space with an extra space in first place

# test if user given phone is contained in the list
if [[ ${phoneBrandList} =~ (^|[[:space:]])"${userPhoneBrand}"($|[[:space:]]) ]]; then
    echo "found it !"
fi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.