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, ksh, yash, 의 경우 와 같은 특정 문자를 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 0( return 0함수/소스 파일에서 사용됨).

관련 정보