如何在bash脚本中组合AND和OR条件用于if条件?

sij*_*703 4 unix bash if-statement

我试图在if条件下的bash脚本中组合逻辑AND&OR.不知何故,我没有得到所需的输出,很难排除故障.我试图验证传递给shell脚本的输入参数没有参数,并且传递的第一个参数是否有效.

if [ "$#" -ne 1 ] && ([ "$1" == "ABC" ] || [ "$1" == "DEF" ] || [ "$1" == "GHI" ] || [ "$1" == "JKL" ]) 
then
echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]"
exit 1
fi
Run Code Online (Sandbox Code Playgroud)

谁能指出这里出了什么问题?

anu*_*ava 5

BASH实际上允许在内部使用扩展的glob [[ ... ]]并且也在&&内部.

所以你可以这样做:

if [[ $# -ne 1 && $1 == @(ABC|DEF|GHI|JKL) ]]; then
   echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]"
   exit 1
fi
Run Code Online (Sandbox Code Playgroud)

  • 在4.1之前,您只需要使用`shopt -s\textglob`明确启用它. (2认同)

mkl*_*nt0 5

你的陈述的直接问题是逻辑:你可能想写:

if [ "$#" -ne 1 ] || ! ([ "$1" = "ABC" ] || [ "$1" = "DEF" ] || [ "$1" = "GHI" ] || [ "$1" = "JKL" ]) 
then
  echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]" >&2
  exit 1
fi
Run Code Online (Sandbox Code Playgroud)

即:中止,如果给出多于1个参数,或者如果给定的单个参数不等于可接受的值之一.

注意!否定括号中的表达式以及使用符合POSIX的形式的字符串相等运算符=(而不是==).

但是,鉴于您正在使用Bash,您可以使用单个[[ ... ]]条件和Bash的正则表达式匹配运算符=~:

if [[ $# -ne 1 || ! $1 =~ ^(ABC|DEF|GHI|JKL)$ ]] 
then
  echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]" >&2
  exit 1
fi
Run Code Online (Sandbox Code Playgroud)

如果不要求POSIX合规,[[ ... ]][ ... ]出于各种原因,这是最好.在手的情况下,$#$1没有需要报价,并且||可以使用里面的条件.

请注意,=~如上所述,在Bash 3.2+中使用,而anubhava的有用答案中extglob使用的隐式语法需要Bash 4.1+; 但是,在早期版本中,您可以显式启用(并恢复其原始值)shell选项:.
extglobshopt -s extglob