与 POSIX sh 兼容而不是利用 bashism 的传统方法是使用 case 语句:
case $level in
-|0|+)
echo "Got it!" ;;
*)
echo "Not a valid value" ;;
esac
也就是说,如果你想使用test,你也可以这样做:
if [ "$LEVEL" != "-" ] && [ "$LEVEL" != "0" ] && [ "$LEVEL" != "+" ]; then
...
fi
!= 是否定字符串比较运算符,= (not ==) 是 POSIX 兼容的正匹配运算符。 (Bash 扩展了 POSIX 以在测试中支持 ==,但是如果您以后尝试为纯 POSIX shell 编写代码,养成使用此扩展的习惯会给您带来麻烦)。
在这里,有bashisms! (以上符合 POSIX)。
在评论中,提出了一个后续问题,即是否可以从变量中读取可能的字符集。一般来说,是的,但有一些警告:
# no spaces in possible_levels, as we're using it to form a pattern
possible_levels='-0+'
possible_levels_pattern="[${possible_levels}]"
if [[ $value = $possible_levels_pattern ]]; then
echo "value contains a valid level"
fi
...作为一种更短的方法,它允许您的输入字符串不加修改地使用,并且几乎是正确的:
# caveat: will say some incorrect strings, like "- 0" or "0 +", are valid levels
possible_levels=' - 0 +'
check_level() {
[[ " $possible_levels " = *" $1 "* ]] && echo "Value is a valid level"
}
...或者,作为另一种实现(冗长,但细节正确):
possible_levels=' - 0 +'
read -a possible_levels_array <<<"$possible_levels"
check_level() {
local possible_level
local value=$1
for possible_level in "${possible_levels_array[@]}"; do
[[ $value = "$possible_level" ]] && return 0
done
return 1
}
if check_level "$value"; then
echo "$value is a valid level"
else
echo "$value is not a valid level"
fi
显然,这是一项繁重的工作,而且一般来说,只要在适当的时候(并且可能在不损失安全性的情况下)对比较进行硬编码,就可以省去试图让事情变得比实际需要的更通用的麻烦。
现在,如果我们可以将变量作为关联数组传入,而不需要支持愚蠢的空格分隔列表,那么它会更短:
declare -A possible_levels=( [-]=1 [+]=1 [0]=1 )
if [[ ${possible_levels[$value]} ]]; then
echo "valid level"
else
echo "invalid level"
fi