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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22259259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:50:15  来源:igfitidea点击:

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

bash

提问by synaptik

In my bash script, I am checking that the first argument is either -, 0, or +, using following ifstatement:

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

LEVEL=
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 ifstatement conditions.

但它给了我错误[: -: integer expression expected,指的是带有if语句条件的行。

I've been trying lots of different syntaxes (e.g., double vs single brackets, quoting vs non-quoting the variables and string literals), but I can't figure it out.

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

回答by Charles Duffy

The conventional approach, compatible with POSIX sh rather than leveraging bashisms, is to use the casestatement:

与 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. (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).

!=是否定字符串比较运算符,并且=(not ==)是与 POSIX 兼容的正匹配运算符。(Bash 扩展了 POSIX 以支持==测试,但是如果您以后尝试为纯 POSIX shell 编写代码,养成使用此扩展的习惯会给您带来麻烦)。



Below here, there be bashisms! (Above is POSIX compliant).

在这里,有bashisms!(以上是符合 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 almostcorrect:

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

# caveat: will say some incorrect strings, like "- 0" or "0 +", are valid levels
possible_levels=' - 0 +'
check_level() {
  [[ " $possible_levels " = *"  "* ]] && 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=
  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

回答by anubhava

You can use [[ and ]]use a selector:

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

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