简体   繁体   English

Bash If语句,检查字符串是否等于几个字符串文字之一

[英]Bash If-statement to check If string is equal to one of several string literals

In my bash script, I am checking that the first argument is either - , 0 , or + , using following if statement: 在我的bash脚本中,我使用以下if语句检查第一个参数是-0还是+

LEVEL=$1
if [ "$LEVEL" -ne "-" ] && [ "$LEVEL" -ne "0" ] && [ "$LEVEL" -ne "+" ]
then
     echo "The value of LEVEL must be either -, 0, or +!"
     exit 1
fi

But it's giving me the error [: -: integer expression expected , referring to the line with the if statement conditions. 但这给了我错误[: -: integer expression expected ,指的是带有if语句条件的行。

I've been trying lots of different syntaxes (eg, double vs single brackets, quoting vs non-quoting the variables and string literals), but I can't figure it out. 我一直在尝试许多不同的语法(例如,双括号与单括号,引用与不引用变量和字符串文字),但我无法弄清楚。

The conventional approach, compatible with POSIX sh rather than leveraging bashisms, is to use the case statement: 与POSIX sh兼容而不是利用bashisms的常规方法是使用case语句:

case $level in
   -|0|+)
     echo "Got it!" ;;
   *)
     echo "Not a valid value" ;;
esac

That said, if you wanted to use test , you could do that too: 就是说,如果您想使用test ,也可以这样做:

if [ "$LEVEL" != "-" ] && [ "$LEVEL" != "0" ] && [ "$LEVEL" != "+" ]; then
  ...
fi

!= is the negating string comparison operator, and = (not == ) is the POSIX-compatible positive-matching one. !=是负数字符串比较运算符,而= (不是==是POSIX兼容的正匹配数。 (Bash extends POSIX to support == in test, but making a habit of using this extension will get you into trouble if you try to write code for a pure POSIX shell later). (Bash在测试中将POSIX扩展为支持== ,但是养成使用此扩展的习惯会使您在以后尝试为纯POSIX shell编写代码时遇到麻烦)。


Below here, there be bashisms! 在这里下面,有bashisms! (Above is POSIX compliant). (以上是POSIX兼容的)。


In a comment, a follow-up question was asked, in terms of whether the set of possible characters could be read from a variable. 在评论中,有人问了一个后续问题,即是否可以从变量中读取可能的字符集。 In general, yes, though there are some caveats: 通常,是的,尽管有一些警告:

# 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

...As an even shorter approach that allows your input string to be used unmodified, and is almost correct: ...作为一种更短的方法,允许您不修改输入字符串就使用它,并且几乎是正确的:

# 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"
}

...or, as yet another implementation (verbose, but correct in the particulars): ...,或作为另一种实现方式(详细,但在细节上正确):

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

Obviously, this is a lot of work, and in general, just hardcoding the comparisons when appropriate (and possible without a loss of safety) will save you trouble over trying to make things more generic than they truly need to be. 显然,这是很多工作,总的来说,仅在适当的时候对比较进行硬编码(并且可能会在不损失安全性的情况下),将使您避免尝试使事情变得比实际需要的更为通用。

Now, if we could pass in the variable as an associative array, without needing to support the silly space-separated-list thing, that makes it much shorter: 现在,如果我们可以将变量作为关联数组传递,而无需支持愚蠢的以空格分隔的列表,则它会变得更短:

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

You can use [[ and ]] use a selector: 您可以使用[[ and ]]使用选择器:

if [[ "$LEVEL" == [0+-] ]]; then
  echo "got it"
fi

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM