要检查的Bash If-statement如果string等于几个字符串文字中的一个

syn*_*tik 9 bash

在我的bash脚本,我检查的第一个参数是要么-,0或者+使用下面if的语句:

LEVEL=$1
if [ "$LEVEL" -ne "-" ] && [ "$LEVEL" -ne "0" ] && [ "$LEVEL" -ne "+" ]
then
     echo "The value of LEVEL must be either -, 0, or +!"
     exit 1
fi
Run Code Online (Sandbox Code Playgroud)

但它给了我错误[: -: integer expression expected,指的是if声明条件的行.

我一直在尝试许多不同的语法(例如,双重与单一括号,引用与非引用变量和字符串文字),但我无法弄明白.

Cha*_*ffy 17

与POSIX sh兼容而不是利用bashisms的传统方法是使用以下case语句:

case $level in
   -|0|+)
     echo "Got it!" ;;
   *)
     echo "Not a valid value" ;;
esac
Run Code Online (Sandbox Code Playgroud)

也就是说,如果你想使用test,你也可以这样做:

if [ "$LEVEL" != "-" ] && [ "$LEVEL" != "0" ] && [ "$LEVEL" != "+" ]; then
  ...
fi
Run Code Online (Sandbox Code Playgroud)

!=是否定字符串比较运算符,= (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
Run Code Online (Sandbox Code Playgroud)

...作为一种更短的方法,允许您的输入字符串未经修改地使用,并且几乎是正确的:

# 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"
}
Run Code Online (Sandbox Code Playgroud)

......或者,作为另一种实施方式(详细,但在详情中是正确的):

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
Run Code Online (Sandbox Code Playgroud)

显然,这需要做很多工作,而且一般情况下,只需在适当的时候对比较进行硬编码(并且可能不会失去安全性),这样可以避免在尝试使事情变得比他们真正需要的更通用时遇到麻烦.

现在,如果我们可以将变量作为关联数组传递,而不需要支持愚蠢的空格分隔列表事物,那么它会更短:

declare -A possible_levels=( [-]=1 [+]=1 [0]=1 )
if [[ ${possible_levels[$value]} ]]; then
  echo "valid level"
else
  echo "invalid level"
fi
Run Code Online (Sandbox Code Playgroud)


anu*_*ava 7

您可以使用[[ and ]]选择器:

if [[ "$LEVEL" == [0+-] ]]; then
  echo "got it"
fi
Run Code Online (Sandbox Code Playgroud)

  • +1 - 很好地使用了bashisms,虽然我倾向于使用`=`而不是`==`来避免构建手指内存,这会强迫人们编写非POSIX代码而不会有意义(而`[[] ]`是一种实际上增加价值的不相容性,`==`vs` =`只是糖) (2认同)
  • @CharlesDuffy是的,甚至不是*好*糖.我已经用C/C++编程了20多年,甚至我认为`==`在shell脚本中是不雅观的.我不知道为什么bash人认为它会*请*C程序员.在C中,`==`只是一个必要的邪恶,因为你可以在任何地方做一个`=`(赋值),包括在条件表达式中.还不够,我必须在我的C代码中整天输入`==`.我为什么要在地球上把这种丑陋的东西拖到我使用的其他语言中? (2认同)