bash에서 연관 배열 변수를 값으로 참조하는 방법은 무엇입니까?

bash에서 연관 배열 변수를 값으로 참조하는 방법은 무엇입니까?

세 개의 연관 배열이 있습니다.

declare -A start_obj end_obj gopath

start_obj['one']="start-obj-one"
start_obj['two']="start-obj-two"

end_obj['one']="end-obj-one"
end_obj['two']="end-obj-two"

gopath['start']="/path/to/start"
gopath['end']="/path/to/end"

배열의 키를 통해 배열의 키와 값을 얻고 싶습니다 start_obj. 코드는 다음과 같습니다.end_objgopath

for t in "${!gopath[@]}"
do
    current=$t"_obj"[@]
    cd ${gopath[$t]}
    for k in ${!current}
    do    
        printf  "[$t]key is : $k ; value is : ${current[$k]}\n"                                                           
    done
done

그러나 이 코드의 실행 결과는 다음과 같습니다.

[start]key is : start-obj-one ; value is : start_obj[@]
[start]key is : start-obj-two ; value is : start_obj[@]
[end]key is : end-obj-one ; value is : end_obj[@]
[end]key is : end-obj-two ; value is : end_obj[@]

내가 원하는 결과는 다음과 같습니다

[start]key is : one ; value is : start-obj-one
[start]key is : two ; value is : start-obj-two
[end]key is : one ; value is : end-obj-one
[end]key is : two ; value is : end-obj-two

그렇다면 원하는 결과를 얻으려면 코드를 어떻게 수정해야 합니까?

답변1

bash버전 4.3 이상 에서는 nameref 변수를 사용할 수 있습니다.

for t in "${!gopath[@]}"; do
  (
    typeset -n current="${t}_obj"
    cd -P -- "${gopath[$t]}" || exit
    for k in "${!current[@]}"
    do    
      printf '%s\n' "[$t]key is: $k; value is: ${current[$k]}"
    done
  )
done

이전 버전의 경우 다음을 사용해야 합니다 eval.

for t in "${!gopath[@]}"; do
  (
    cd -P -- "${gopath[$t]}" || exit
    eval '
      for k in "${!'"$t"'_obj[@]}"
      do    
        printf "%s\n" "[$t]key is: $k; value is: ${'"$t"'_obj[$k]}"
      done
    '
  )
done

bash변수 간접 연산자가 있습니다: ${!varname}연산자와는 아무런 관련이 없지만 ${!hash[@]}(실제로 ksh93의 반대쪽에 더 가깝습니다 ${!varname}) 연산자와 결합할 수 없습니다 ${!hash[@]}( varname=hash; for key in "${!!varname[@]}"...작동하지 않음). 여기에서 사용할 수 있는 가변 간접 연산자가 있고 더 오랫동안 연관 배열을 지원한 쉘의 경우 zsh( ${(P)varname})를 사용하여 살펴볼 수 있으며, 이를 통해 키와 값을 동시에 반복할 수도 있습니다.

typeset -A start_obj end_obj gopath
start_obj=(
  one  start-obj-one
  two  start-obj-two
)
end_obj=(
  one  end-obj-one
  two  end-obj-two
)
gopath=(
  start  /path/to/start
  end    /path/to/end
)
for t dir ("${(kv@)gopath}") (
  cd -P -- "$dir" || exit
  current=${t}_obj
  for key value ("${(kvP@)current}")
    printf '%s\n' "[$t]key is: $key; value is: $value}"
)

어쨌든 bashand zsh(그리고 ksh93연관 배열을 도입하고 bash복사를 시도한 첫 번째 셸)에서는 연관 배열이 해시 테이블로 구현되므로 요소가 특정 순서로 저장되지 않으므로 위의 코드는 요소를 반복하여 무작위 순서로 나타납니다. .

답변2

이전 bash 버전의 경우 다음 명령을 사용하여 이 작업을 수행할 수 있습니다.색인연관 배열이 아닌 배열은 변수 간접 참조를 사용합니다.

$ declare -p start_obj end_obj gopath
declare -A start_obj='([one]="start-obj-one" [two]="start-obj-two" )'
declare -A end_obj='([one]="end-obj-one" [two]="end-obj-two" )'
declare -A gopath='([start]="/path/to/start" [end]="/path/to/end" )'

$ for t in "${!gopath[@]}"; do tmp="${t}_obj[@]"; ary=( "${!tmp}" ); declare -p ary; done
declare -a ary='([0]="start-obj-one" [1]="start-obj-two")'
declare -a ary='([0]="end-obj-one" [1]="end-obj-two")'

우리가 어떻게 얻는지 참고하세요가치하지만열쇠연관 배열.

자세한 내용은 4항을 참조하세요.https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion

관련 정보