bashで連想配列変数を値として参照する方法は?

bashで連想配列変数を値として参照する方法は?

3つの連想配列があります。

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最初のシェル)では、連想配列がハッシュテーブルとして実装されているため、要素は特定の順序で格納されないため、上記のコードは要素を繰り返しランダムな順序で表示されます。 。

おすすめ記事