web-dev-qa-db-ja.com

文字列比較に不等演算子を使用する

PHONE_TYPE変数には、3つの有効な値のいずれかが含まれています。

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

このタイプのタスクにはより明確な方法がありますか?

134
munish

私はあなたが探していると思います:

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)

これは明らかに機能しません。

193
Nils Werner

より短い方法は次のとおりです。

if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|Cisco)$ ]]; then 
  echo "Phone type must be nortel, Cisco or nec."
fi
  • ^ –行頭の開始に一致させるには
  • $ –行末と一致させる
  • =~-Bashの組み込みの正規表現比較演算子
38
0x80

良い答え、そして貴重なレッスン;)メモで補足したいだけです。

どのタイプのテストを使用するかは、コード、構造、環境などに大きく依存します。

別の方法として、次のようにスイッチまたはcaseステートメントを使用することもできます。

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

2つ目の注意点として、大文字の変数名を使用する場合は注意が必要です。これは、ほとんどすべての場合大文字であるシステムによって導入された変数間の衝突を防ぐためです。したがって、$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
13
Runium

ORではなく、ANDを使用する必要があります。

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

または

if [ "$PHONE_TYPE" != "NORTEL" -a "$PHONE_TYPE" != "NEC" -a "$PHONE_TYPE" != "Cisco" ]
then
11
jlliagre

上記の回答を修正するには(まだコメントはできません):

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"も一致します。

2
Will

@ 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
0
tdaget

代わりに[[を使用してください

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