如何在 bash 脚本中为 if 条件组合 AND 和 OR 条件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38067413/
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
How to combine AND and OR condition in bash script for if condition?
提问by sijo0703
I was trying to combine logical AND & OR in a bash script within if condition. Somehow I am not getting the desired output and it is hard to troubleshoot. I am trying to validate the input parameters passed to a shell script for no parameter and the first parameter passed is valid or not.
我试图在 if 条件下的 bash 脚本中结合逻辑 AND & OR。不知何故,我没有得到所需的输出,并且很难进行故障排除。我正在尝试验证传递给没有参数的 shell 脚本的输入参数,并且传递的第一个参数是否有效。
if [ "$#" -ne 1 ] && ([ "" == "ABC" ] || [ "" == "DEF" ] || [ "" == "GHI" ] || [ "" == "JKL" ])
then
echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]"
exit 1
fi
Can anyone point out what is going wrong here?
谁能指出这里出了什么问题?
回答by mklement0
The immediate problem with your statement is one of logic: you probably meant to write:
您的陈述的直接问题是逻辑之一:您可能打算写:
if [ "$#" -ne 1 ] || ! ([ "" = "ABC" ] || [ "" = "DEF" ] || [ "" = "GHI" ] || [ "" = "JKL" ])
then
echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]" >&2
exit 1
fi
That is: abort, if either more than 1 argument is given OR if the single argument given does NOT equal one of the acceptable values.
即:中止,如果给出了 1 个以上的参数,或者如果给出的单个参数不等于可接受的值之一。
Note the !
to negate the expression in parentheses and the use of the POSIX-compliant form of the string equality operator, =
(rather than ==
).
请注意!
否定括号中的表达式以及使用符合 POSIX 形式的字符串相等运算符=
(而不是==
)。
However, given that you're using Bash, you can make do with a single [[ ... ]]
conditional and Bash's regular-expression matching operator, =~
:
但是,鉴于您使用的是 Bash,您可以使用单个[[ ... ]]
条件和 Bash 的正则表达式匹配运算符=~
:
if [[ $# -ne 1 || ! =~ ^(ABC|DEF|GHI|JKL)$ ]]
then
echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]" >&2
exit 1
fi
If POSIX compliance is not required, [[ ... ]]
is preferable to [ ... ]
for a variety of reasons.
In the case at hand, $#
and $1
didn't need quoting, and ||
could be used insidethe conditional.
如果不需要 POSIX 合规性,出于各种原因,[[ ... ]]
最好使用POSIX 。在手的情况下,并没有需要报价,并且可以使用里面的条件。[ ... ]
$#
$1
||
Note that =~
as used above works in Bash 3.2+, whereas the implicit extglob
syntax used in anubhava's helpful answerrequires Bash 4.1+;
in earlier versions you can, however, explicitly enable (and restore to its original value after) the extglob
shell option: shopt -s extglob
.
请注意,=~
如上所用,在 Bash 3.2+ 中有效,而anubhava 的有用答案中extglob
使用的隐式语法需要 Bash 4.1+;
但是,在早期版本中,您可以显式启用(并在之后恢复其原始值)shell 选项:。extglob
shopt -s extglob
回答by anubhava
BASH actually allows use of extended glob inside [[ ... ]]
and have &&
inside as well.
BASH 实际上允许在内部使用扩展的 glob[[ ... ]]
并且也有&&
内部。
So you can do:
所以你可以这样做:
if [[ $# -ne 1 && == @(ABC|DEF|GHI|JKL) ]]; then
echo "Usage: ./myscript.sh [ABC | DEF | GHI | JKL]"
exit 1
fi
回答by Taywee
A few things:
一些东西:
[...]
in bash is equivalent to the sametest
command (check the man page), so those && and || are not logical operators, but rather the shell equivalents- Parentheses in POSIX shell are not a grouping operator. They will work here, but they open a subshell, you are better off using standard test options of
-a
and-o
(making your if statementif [ "$#" -ne 1 -a \( "$1" == "ABC" -o "$1" == "DEF" -o "$1" == "GHI" -o "$1" == "JKL" \) ]
, though based on your logic, it sounds like you actually want something likeif [ "$#" -ne 1 -o \( "$1" != "ABC" -a "$1" != "DEF" -a "$1" != "GHI" -a "$1" != "JKL" \) ]
. You probably can get better results with acase
statement like follows:
[...]
在 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 "" in
ABC)
echo "Found ABC"
;;
DEF)
echo "Found DEF"
;;
GHI)
echo "Found GHI"
;;
JKL)
echo "Found JKL"
;;
*)
usage
exit 1
;;
esac
If you want to pass a set of possible static arguments in, you might want to look at the getopts
special shell command.
如果您想传入一组可能的静态参数,您可能需要查看getopts
特殊的 shell 命令。