我正在寻找一个类似这样的“ in”运算符:
if [ "$1" in ("cat","dog","mouse") ]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
与使用多个“或”测试相比,这显然是一条短得多的语句。
我正在寻找一个类似这样的“ in”运算符:
if [ "$1" in ("cat","dog","mouse") ]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
与使用多个“或”测试相比,这显然是一条短得多的语句。
Answers:
您可以使用case
...esac
$ cat in.sh
#!/bin/bash
case "$1" in
"cat"|"dog"|"mouse")
echo "dollar 1 is either a cat or a dog or a mouse"
;;
*)
echo "none of the above"
;;
esac
例如
$ ./in.sh dog
dollar 1 is either a cat or a dog or a mouse
$ ./in.sh hamster
none of the above
随着ksh
,bash -O extglob
或者zsh -o kshglob
,你也可以使用扩展的glob模式:
if [[ "$1" = @(cat|dog|mouse) ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
else
echo "none of the above"
fi
随着bash
,ksh93
或者zsh
,你也可以使用正则表达式比较:
if [[ "$1" =~ ^(cat|dog|mouse)$ ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
else
echo "none of the above"
fi
=~
不是POSIX单托架测试内有效
[
是POSIX,但是[[
是bash,ksh的扩展功能(显然它起源于此,而zsh。 case
示例是所有POSIX中的大多数)
case "$1" in
不需要用引号引起来,在该令牌中不执行词拆分或路径名扩展。
bash中没有“ in”测试,但是有一个正则表达式测试(bourne中没有):
if [[ $1 =~ ^(cat|dog|mouse)$ ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
并且通常使用变量编写(较少的引用问题):
regex='^(cat|dog|mouse)$'
if [[ $1 =~ $regex ]]; then
echo "dollar 1 is either a cat or a dog or a mouse"
fi
对于较旧的Bourne外壳,您需要使用大小写匹配:
case $1 in
cat|dog|mouse) echo "dollar 1 is either a cat or a dog or a mouse";;
esac
case
如果您有固定的宠物要配对,使用a 会很好。但是,如果您需要在运行时中构建模式,它将无法正常工作,因为case
无法从扩展参数中解释替代。
这将仅匹配文字字符串cat|dog|mouse
:
patt='cat|dog|mouse'
case $1 in
$patt) echo "$1 matches the case" ;;
esac
但是,您可以将变量与正则表达式匹配使用。只要不引用该变量,该变量中的任何正则表达式运算符都有其特殊含义。
patt='cat|dog|mouse'
if [[ "$1" =~ ^($patt)$ ]]; then
echo "$1 matches the pattern"
fi
您也可以使用关联数组。检查密钥是否存在与in
Bash提供的运算符最接近。虽然语法有点丑陋:
declare -A arr
arr[cat]=1
arr[dog]=1
arr[mouse]=1
if [ "${arr[$1]+x}" ]; then
echo "$1 is in the array"
fi
您可以case
在if
测试中使用一条语句,但是代码看起来有些毛茸茸:
if case "$1" in (cat|dog|mouse) true ;; (*) false; esac; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
或稍短,
if ! case "$1" in (cat|dog|mouse) false; esac; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
这是使用case
子句只是为了对该if
子句进行模式匹配。它引入了不必要的对/错测试。
最好只使用case
:
case "$1" in
cat|dog|mouse)
printf '"%s" is one of cat, dog or mouse\n' "$1"
;;
*)
printf '"%s" is unknown\n' "$1"
esac
不要这样做:
is_one_of () {
eval "case $1 in ($2) return 0; esac"
return 1
}
if is_one_of "$1" 'cat|dog|mouse'; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
或这个:
is_one_of () (
word=$1
shift
IFS='|'
eval "case $word in ($*) return 0; esac"
return 1
)
if is_one_of "$1" cat dog mouse; then
printf '"%s" is one of cat, dog or mouse\n' "$1"
else
printf '"%s" is unknown\n' "$1"
fi
...因为您只是添加了更多危险的东西,只是为了能够if
在代码中使用一个语句来代替一个完全合理的case
语句。
eval
对的case
声明在这种情况下,它会更容易出错。
"$1"|"$2"|"$3"
。也是unix.stackexchange.com/a/234415/85039 但是,是的,这有点毛。