在 bash 中一起使用 case 和数组

red*_*pet 4 scripting bash array shell-script case

是否可以使用case?检查变量是否包含在数组中?我想做类似的事情

ARR=( opt1 opt2 opt3 );

case $1 in
    $ARR)
        echo "Option is contained in the array";
    *)
        echo "Option is not contained in the array";
esac
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 6

有了ksh93,由于这个错误,你可以这样做:

IFS='|'
ARR=( opt1 opt2 opt3 )

IFS='|'
case $1 in
  (@("${ARR[*]}"))
    echo "Option is contained in the array";;
  (*)
    echo "Option is not contained in the array";;
esac
Run Code Online (Sandbox Code Playgroud)

(我不会依赖它,因为该错误可能会在未来得到修复)。

使用zsh,您可以执行以下操作:

case ${ARR[(Ie)$1]}
  (0)
    echo "Option is not contained in the array";;
  (*)
    echo "Option is contained in the array";;
esac
Run Code Online (Sandbox Code Playgroud)

(不过,您可能更愿意在if ((ARR[(Ie)$1])); then echo is present...这里使用而不是 case 构造)。

${array[(I)pattern]}返回与数组中的模式匹配的最后一个元素的索引,否则返回 0。该e标志用于精确匹配(与模式匹配相反)。

使用bash, ksh, yash, zsh,如果您准备好假设$ARR并且$1不包含某个字符,例如@,并且$ARR不会为空,您可以执行以下操作:

IFS=@
case "@${ARR[*]}@" in
  (*"@$1@"*)
    echo "Option is contained in the array";;
  (*)
    echo "Option is not contained in the array";;
esac
Run Code Online (Sandbox Code Playgroud)

使用bash -O extglob, zsh -o kshglob -o globsubst,您可以定义一个帮助器,它根据数组的元素构建一个模式:

arraypat() {
  awk '
    BEGIN{
      if (ARGC <= 1) print "!(*)"
      else {
        for (i = 1; i < ARGC; i++) {
          gsub(/[][|<>\\?*()]/, "[&]", ARGV[i])
          s = s sep ARGV[i]
          sep = "|"
        }
        print "@(" s ")"
      }
    }' "$@"
}

case $1 in
  ($(arraypat "${ARR[@]}"))
    echo "Option is contained in the array";;
  (*)
    echo "Option is not contained in the array";;
esac
Run Code Online (Sandbox Code Playgroud)


Kus*_*nda 3

并不是真正以紧凑且易于使用的方式。请记住,在您的示例中$ARR,它将仅扩展到数组的第一个元素opt1

您可以使用"${ARR[@]}",但是使用您的数据可能会给字符串带来误报1 opt

对于更新版本的bash,您可以考虑使用关联数组:

declare -A arr
arr=( [opt1]=1 [opt2]=1 [opt3]=1 )

if [[ "${arr[$1]}" -eq 1 ]]; then
   # $1 is a key in arr
else
   # is not
fi
Run Code Online (Sandbox Code Playgroud)