I tried to check if the PHONE_TYPE variable contains one of three valid values.
if [ "$PHONE_TYPE" != "NORTEL" ] || [ "$PHONE_TYPE" != "NEC" ] ||
[ "$PHONE_TYPE" != "CISCO" ]
then
echo "Phone type must be nortel,cisco or nec"
exit
fi
The above code did not work for me, so I tried this instead:
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
Are there cleaner ways for this type of task?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I guess you’re looking for:
if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] && [ "$PHONE_TYPE" != "CISCO" ]
The rules for these equivalents are called De Morgan’s laws and in your case meant:
not(A || B || C) => not(A) && not(B) && not (C)
Note the change in the boolean operator or and and.
Whereas you tried to do:
not(A || B || C) => not(A) || not(B) || not(C)
Which obviously doesn’t work.
Method 2
A much shorter way would be:
if [[ ! $PHONE_TYPE =~ ^(NORTEL|NEC|CISCO)$ ]]; then echo "Phone type must be nortel, cisco or nec." fi
^– To match a starting at the beginning of line$– To match end of the line=~– Bash’s built-in regular expression comparison operator
Method 3
Good answers, and an invaluable lesson 😉 Only want to supplement with a note.
What type of test one choose to use is highly dependent on code, structure, surroundings etc.
An alternative could be to use a switch or case statement as in:
case "$PHONE_TYPE" in
"NORTEL"|"NEC"|"CISCO")
echo "OK"
;;
*)
echo "Phone type must be nortel,cisco or nec"
;;
esac
As a second note you should be careful by using upper-case variable names. This is to prevent collision between variables introduced by the system, which almost always is all upper case. Thus $phone_type instead of $PHONE_TYPE.
Though that one is safe, if you have as habit using all upper case, one day you might say IFS="boo" and you’re in a world of hurt.
It will also make it easier to spot which is what.
Not a have to but a would strongly consider.
It is also presumably a good candidate for a function. This mostly makes the code easier to read and maintain. E.g.:
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
Method 4
You should use ANDs, not ORs.
if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] && [ "$PHONE_TYPE" != "CISCO" ] then
or
if [ "$PHONE_TYPE" != "NORTEL" -a "$PHONE_TYPE" != "NEC" -a "$PHONE_TYPE" != "CISCO" ] then
Method 5
To correct an above answer (as I can’t comment yet):
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
Please note that you need at least bash 4 for this use of =~
It doesn’t work in bash 3.
I tested on MS Windows 7 using bash 4.3.46 (works fine) and bash 3.1.17 (didn’t work)
The LHS of the =~ should be in quotes. Above, PHONE_TYPE=”SPACE TEL” would match too.
Method 6
Just a variation proposal based on @0x80 solution:
# 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
Method 7
Use [[ instead
if [[ "$PHONE_TYPE" != "NORTEL" ]] || [[ "$PHONE_TYPE" != "NEC" ]] || [[ "$PHONE_TYPE" != "CISCO" ]] then echo "Phone type must be nortel,cisco or nec" exit 1 fi
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0