The immediate problem with your statement is one of logic: you probably meant to write:
if [ "$#" -ne 1 ] || ! ([ "$1" = "ABC" ] || [ "$1" = "DEF" ] || [ "$1" = "GHI" ] || [ "$1" = "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.
Note the !
to negate the expression in parentheses and the use of the POSIX-compliant form of the string equality operator, =
(rather than ==
).
However, given that you're using Bash, you can make do with a single [[ ... ]]
conditional and Bash's regular-expression matching operator, =~
:
if [[ $# -ne 1 || ! $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 inside the conditional.
Note that =~
as used above works in Bash 3.2+, whereas the implicit extglob
syntax used in anubhava's helpful answer requires 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
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…