zsh는 간접 확장을 통해 연관 배열의 키가 존재하는지 테스트합니다.

zsh는 간접 확장을 통해 연관 배열의 키가 존재하는지 테스트합니다.

따라서 다음과 같이 간접 확장을 통해 일반 매개변수의 존재 여부를 테스트할 수 있다는 것을 알고 있습니다.

foo=1
bar=foo
(( ${(P)+bar} )) && print "$bar exists"

다음을 수행하여 연관 배열에 키가 존재하는지 테스트할 수 있다는 것을 알고 있습니다.

foo=([abc]=1)
(( ${+foo[abc]} )) && print "abc exists"

그러나 두 가지를 결합하고 간접 확장을 통해 키가 연관 배열에 존재하는지 테스트하는 방법을 알 수 없습니다. eval을 사용하지 않는 것이 가능한가요?

다음을 포함하여 여러 가지 조합을 시도했지만 그 중 아무 것도 작동하지 않습니다.

foo=([abc]=1)
bar=foo
(( ${(P)+bar[abc]} )) && print "$bar has key abc" # Test fails
(( ${(P)+${bar}[abc]} )) && print "$bar has key abc" # Passes for nonexistant keys
(( ${${(P)+bar}[abc]} )) && print "$bar has key abc" # Test fails
(( ${${(P)bar}+[abc]} )) && print "$bar has key abc" # prints "zsh: bad output format specification"

답변1

됐어여기서 토론하세요. 값 전달을 방지하려면 ${:-word}다른 매개변수 확장(예:)에서 올바른 형식의 문자열을 사용한 다음 다음을 통해 확장해야 합니다 ${(P)+...}.

(( ${(P)+${:-${bar}[abc]}} )) && print OK || print FAIL

답변2

을 사용하는 방법을 모르지만 ${+param}다음을 사용할 수 있습니다 [[ -v $param ]].

foo=([abc]=1)
bar=foo

[[ -v "$bar""[abc]" ]] && print "$bar has key abc"
# or "$bar"[abc] or $bar''[abc] or $bar'[abc]'
# or any other way to suppress $bar[abc] being interpreted as a value in $bar

답변3

나는 표현식을 작성하고 eval을 사용하는 것이 트릭이라는 것을 알았습니다.

  typeset -A ARRAY_TEST

  ARRAY_TEST[key1]=
  ARRAY_TEST[key2]=value2

  ARRAY_NAME=ARRAY_TEST

  # Note: ${NAME+1} will return 1 if a variable is set, otherwise nothing
  #       for example, ${ARRAY_TEST[key1]+1} will be 1 and
  #       but ${ARRAY_TEST[key3]+1} will be nothing  
  [[ $(eval "echo \${${ARRAY_NAME}[key1]+1}") == 1 ]] && echo has key1 || echo no key1
  [[ $(eval "echo \${${ARRAY_NAME}[key2]+1}") == 1 ]] && echo has key2 || echo no key2
  [[ $(eval "echo \${${ARRAY_NAME}[key3]+1}") == 1 ]] && echo has key3 || echo no key3

# Outputs:
#
#    has key1
#    has key2
#    no key3

결국 이를 위한 함수를 만들었습니다.

function array-has-value() {
  local testVariable=$1
  local keyValue=$2

  [[ $(eval "echo \${${testVariable}[$keyValue]+1}") == 1 ]] && return 0 || return 1
}

다음은 위와 동일한 결과를 생성합니다.

array-has-value ARRAY_TEST key1 && echo has key1 || echo no key1
array-has-value ARRAY_TEST key2 && echo has key2 || echo no key2
array-has-value ARRAY_TEST key3 && echo has key3 || echo no key3

답변4

내가 찾은 또 다른 답변은 다음과 같습니다.

typeset -A foo=([abc]=def)

has_key() {
   local var="${1}[$2]"
   (( ${(P)+${var}} )) && return 0
   return 1
}
has_key foo abc && print "foo has abc"
has_key foo def || print "foo doesn't have def"
# Outputs:
# foo has abc
# foo doesn't have def

관련 정보