세 개의 연관 배열이 있습니다.
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_obj
gopath
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}"
)
어쨌든 bash
and 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