我试图合并逻辑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
有人能指出这里出了什么问题吗?
答案 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)
一些事情:
[...]
等同于test
命令(查看手册页),因此&&和和||不是逻辑运算符,而是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命令。