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

时间:2016-06-28 05:02:22

标签: bash unix if-statement

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

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

有人能指出这里出了什么问题吗?

3 个答案:

答案 0 :(得分:5)

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

所以你可以这样做:

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

答案 1 :(得分: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

那就是:abort,如果给出多于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

如果不需要POSIX合规性,则[[ ... ]]优于a variety of reasons [ ... ]。 在目前的情况下,$#$1不需要引用,||可以在里面使用条件。

请注意,上面使用的=~适用于Bash 3.2+,而anubhava's helpful answer中使用的隐式extglob语法需要Bash 4.1+;
但是,在早期版本中,您可以明确启用{并恢复到其原始值之后的extglob shell选项:shopt -s extglob

答案 2 :(得分:1)

一些事情:

    bash中的
  • [...]等同于test命令(查看手册页),因此&&和和||不是逻辑运算符,而是shell等价物
  • POSIX shell中的括号不是分组运算符。他们会在这里工作,但他们打开一个子shell,你最好使用-a-o的标准测试选项(制作你的if语句if [ "$#" -ne 1 -a \( "$1" == "ABC" -o "$1" == "DEF" -o "$1" == "GHI" -o "$1" == "JKL" \) ],虽然根据你的逻辑,它听起来就像你真的想要if [ "$#" -ne 1 -o \( "$1" != "ABC" -a "$1" != "DEF" -a "$1" != "GHI" -a "$1" != "JKL" \) ]这样的东西。你可能会用case语句得到更好的结果,如下所示:
usage() {
    echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]"
}


if [ "$#" -ne 1 ] 
then
    usage
    exit 1
fi

case "$1" in
    ABC)
        echo "Found ABC"
        ;;
    DEF)
        echo "Found DEF"
        ;;
    GHI)
        echo "Found GHI"
        ;;
    JKL)
        echo "Found JKL"
        ;;
    *)
        usage
        exit 1
        ;;
esac

如果要传递一组可能的静态参数,可能需要查看getopts特殊shell命令。