ZSH: 연관 배열 이름과 내용을 동적으로 설정하는 방법은 무엇입니까?

ZSH: 연관 배열 이름과 내용을 동적으로 설정하는 방법은 무엇입니까?

다음과 같이 연관 배열을 설정했습니다.

$ foo=test
$ set -A $foo "a b" "1 2" "c d" "3 4"
$ for key val in "${(@kv)test}"; do echo "$key -> $val" done
a b -> 1 2
c d -> 3 4

"a b" "1 2" "c d" "3 4"배열 내용을 변수로 바꾸는 방법은 무엇입니까?

답변1

set -A array value1 value21980년대 초반에 일반 배열을 정의하는 데 사용된 오래된 ksh 구문입니다. 연관 배열을 정의하지 않으며 ksh88과만 호환됩니다.

k매개변수 확장 플래그는 v연관 배열의 변수에만 의미가 있습니다. 다른 유형의 변수(일반 배열 포함)의 경우 단순히 무시됩니다. 따라서 여기서는 "${(@kv)test}"또는 일반 배열²의 모든 요소로 확장됩니다."${(@)test}""$test[@]"

연관 배열을 선언하려면 최신 방식을 사용하는 것이 좋습니다.

assoc=(
  'key 1' 'value 1'
  'key 2' 'value 2'
)

문법³assoc연관배열로 선언한 후그리고:

typeset -A assoc

최신 버전에서는 이제 typeset이중 키워드/내장이므로 다음을 사용하여 동시에 선언하고 할당할 수도 있습니다.

typeset -A assoc=(
  'key 1' 'value 1'
  'key 2' 'value 2'
)

그러면 다음과 같이 할 수 있습니다:

printf '"%s" => "%s"\n' "${(@kv)assoc}"

또는

for k v ("${(@kv)assoc}") print -r -- "$k => $v"

또는:

for k ("${(@k)assoc}") print -r -- "$k => $assoc[$k]"

해당 키와 값을 반복합니다.

키와 값 목록의 변수에 저장된 이름으로 연관 배열을 정의하려면 다음을 사용할 수 있습니다.

setassoc() {
  typeset -gA $1; shift
  eval "$1"='( "$@[2,-1]" )'
}
foo=test
setassoc $foo 'key 1' 'value 1' 'key 2' 'value 2'

또는 키와 값 목록이 일반 배열 변수에 저장되어 있는 경우:

array=('key 1' 'value 1' 'key 2' 'value 2')
setassoc $foo "$array[@]"

그런데 set -A여기를 사용하면 피할 수 있지만 eval(여기서 이런 식으로 사용하는 것이 잘못된 것은 아닙니다 eval) 먼저 변수를 연관 배열로 설정해야 합니다.

foo=test
typeset -A $foo
set -A $foo "$array[@]"

ksh 에뮬레이션이 활성화된 경우(구체적으로 ksharrays해당 옵션이 활성화된 경우) 이를 다음과 같이 변경해야 합니다.

set -A $foo -- "$array[@]"

1 David Korn은 Bourne 쉘이 이미 사용 중이었기 -A때문에 이 옵션을 선택했습니다. 또한 ksh93 또는 zsh에서 행을 배열로 읽는 데 사용되는 set -a이유도 설명했습니다 . 배열 디자인이 ksh88을 기반으로 하고( 어레이 디자인이 ksh보다 csh에 더 가깝지만) 대신 선택되었지만 지원되지 않습니다 . 혼란의 원인 중 하나는 일반 배열 선언과 연관 배열 선언(둘 다 ksh에서) 입니다.read -Abashset -Azshread -aread -Atypeset -atypeset -A

² 그리고 for k v합계를 배열의 요소에 차례로 할당합니다. 그러면 출력이 설명되고 할당과 동일한 순서인 이유가 설명됩니다(반면 연관 배열의 경우 순서가 보장되지 않음).kv

³ 구문은 실제로~에서zsh는 1990년에 등장했고 나중에 ksh93(큰 변수 유형의 일부로 복합 변수도 포함됨)과 bash(배열은 1996년 2.0까지 나타나지 않음)에 등장했지만 csh에서 많은 영감을 받았습니다(p. A 1970년대 후반의 배열을 사용한 쉘) 구문은 다음과 같습니다.set array = (foo bar)

관련 정보