Bashでケースと配列を一緒に使用する

Bashでケースと配列を一緒に使用する

変数が配列に含まれていることを確認することは可能ですか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

答え1

そして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

(今後はバグが修正される可能性があるため、これには依存しません。)

これにより、zsh次のことができます。

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

if (( $ARR[(Ie)$1] )); then echo is present...しかし、ここではケース構成の代わりに使用する方が良いかもしれません)。

${array[(I)pattern]}パターンに一致する配列の最後の要素インデックスを返し、そうでない場合は0を返します。このeフラグは精密一致(関連模様マッチ)。

bash、、、、kshyash場合などの特定の文字をzsh想定する準備ができていて、$ARRその文字がnullでない場合は、次のことができます。$1@$ARR

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

を使用すると、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

答え2

実際には小さくて使いやすい方法ではありません。あなたの例では、$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

答え3

なぜこれを行うのですcaseか?要素ごとの一致ではなく、文字列パターンの一致に使用されます。

正直に言うと、テストを頻繁に「含める」必要があり、テストを短縮したい場合は、見苦しい解決策を使用するのではなく、難しい部分を関数に入れるだけです。

#!/bin/bash
ARR=( foo bar doo );

contains() {
        typeset _x;
        typeset -n _A="$1"
        for _x in "${_A[@]}" ; do
                [ "$_x" = "$2" ] && return 0
        done
        return 1
}

if contains ARR "$1" ; then
        echo "\"$1\" is contained in ARR"
else
        echo "\"$1\" not contained in ARR"
fi

(これも適用されるべきですksh

答え4

ユーザーにはbash段落ではなく演算子があります;;&。節では配列を直接サポートしていませんが、case非常にエレガントです。

ARR=( opt1 opt2 opt3 );

case $1 in
    *)
        [[ ${ARR[*]} =~ $1 ]] \
            && echo "Option is contained in the array" \
            && exit 0
        ;;&

    *)
        echo "Option is not contained in the array"
        ;;
esac

;;&(つまり、非短絡)は、$1後続のケースセクションの評価を保証しますexit 0return 0関数/ソースファイルで使用されます)。

関連情報