Nounset 쉘 옵션을 사용하여 Bash 4.2 이전 버전에 변수가 정의되어 있는지 테스트하려면 어떻게 해야 합니까?

Nounset 쉘 옵션을 사용하여 Bash 4.2 이전 버전에 변수가 정의되어 있는지 테스트하려면 어떻게 해야 합니까?

-v"GNU bash, 버전 4.2" 이전의 Bash 버전에 대해 이 명령 옵션과 동등한 대안이 있습니까 test? 예를 들어:

shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo

답변1

모든 POSIX 쉘에 이식 가능:

if [ -n "${foobar+1}" ]; then
  echo "foobar is defined"
else
  echo "foobar is not defined"
fi

${foobar:+1}foobar비어있든 정의되지 않든 동일한 방식으로 처리 하려면 그렇게 하십시오. 정의되지 않은 ${foobar-}경우 빈 문자열을 가져오는 데 사용할 수도 있고 foobar, 그렇지 않은 경우 값을 가져오는 데 사용할 수도 foobar있습니다(또는 뒤에 다른 기본값을 추가할 수도 있습니다 -).

ksh에서는 foobar와 같이 선언되었지만 정의되지 않은 경우 빈 문자열로 확장됩니다 typeset -a foobar.${foobar+1}

Zsh 변수가 선언되지 않았지만 설정되지 않았습니다. typeset -a foobar빈 배열을 생성합니다.

Bash에서 배열은 다양하고 놀라운 방식으로 작동합니다. 비어 있지 않은 배열인 경우 에만 ${a+1}확장됩니다 .1a

typeset -a a; echo ${a+1}    # prints nothing
e=(); echo ${e+1}            # prints nothing!
f=(''); echo ${f+1}          # prints 1

동일한 원칙이 연관 배열에 적용됩니다. 배열 변수에 비어 있지 않은 인덱스 세트가 있는 경우 배열 변수는 정의된 배열 변수로 간주됩니다.

어떤 유형의 변수가 정의되었는지 테스트하는 또 다른 bash 관련 방법은 해당 변수가 undefed로 보고되었는지 확인하는 것입니다.${!PREFIX*}${foobar+1}unset foobar; typeset -a foobar

case " ${!foobar*} " in
  *" foobar "*) echo "foobar is defined";;
  *) echo "foobar is not defined";;
esac

이는 다음과 같습니다.typeset -p foobar또는의 반환 값을 테스트합니다.declare -p foobar, 그러나 typeset -p foobar선언되었지만 할당되지 않은 변수에서는 실패합니다.

bash에서는 ksh와 마찬가지로 set -o nounset; typeset -a foobar; echo $foobar정의되지 않은 변수를 확장하려고 하면 오류가 발생합니다 foobar. ksh와 달리 set -o nounset; foobar=(); echo $foobar(또는 echo "${foobar[@]}")도 오류를 유발합니다.

여기에 설명된 모든 경우에 아래 오류가 발생할 ${foobar+1}경우에만 빈 문자열로의 확장이 수행됩니다 .$foobarset -o nounset

답변2

Giles의 답변을 요약하여 다음과 같은 규칙을 개발했습니다.

  1. [[ -v foobar ]]Bash 버전 >= 4.2에서 사용되는 변수.
  2. declare -p foobar &>/dev/nullBash 버전 < 4.2에서 사용하기 위한 배열 변수입니다.
  3. (( ${foo[0]+1} ))또는 (( ${bar[foo]+1} ))인덱스 배열( -a) 및 키 -A배열( ) declare의 아래 첨자 로 각각 사용합니다 . 옵션 1과 2는 여기서 작동하지 않습니다.

답변3

Bash의 모든 변수에 동일한 기술을 사용하며 작동합니다. 예를 들면 다음과 같습니다.

[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"

산출:

foobar is unset

동시에

foobar=( "val" "val2" )
[ ${foobar} ] && echo "foobar is set" || echo "foobar is unset"

산출:

foobar is set

관련 정보