web-dev-qa-db-ja.com

Bashの多次元連想配列

多次元の連想配列を作成しようとしていますが、助けが必要です。私はレビューしました これで提案されたページSO回答 ですが、それは私をさらに混乱させました。これまでのところ、私が持っているものは次のとおりです:

スクリプト:

#!/bin/bash
declare -A PERSONS
declare -A PERSON
PERSON["FNAME"]='John'
PERSON["LNAME"]='Andrew'
PERSONS["1"]=${PERSON[@]}
PERSON["FNAME"]='Elen'
PERSON["LNAME"]='Murray'
PERSONS["2"]=${PERSON[@]}
for KEY in "${!PERSONS[@]}"; do
 TMP="${PERSONS["$KEY"]}"
 echo "$KEY - $TMP"
 echo "${TMP["FNAME"]}"
 echo "${TMP["LNAME"]}"
done

出力:

1 - John Andrew
John Andrew
John Andrew
2 - Elen Murray
Elen Murray
Elen Murray

ご覧のとおり、forループで$ TMP配列の特定のインデックスにアクセスしようとすると、配列全体が返されます。

[Q] forループ内の$ TMP配列の「FNAME」インデックスと「LNAME」インデックスに個別にアクセスするには、何をする必要がありますか?

ありがとう。

18
Max

あなたがやろうとしていることはできません: bash array は1次元です

$ declare -A PERSONS
$ declare -A PERSON
$ PERSON["FNAME"]='John'
$ PERSON["LNAME"]='Andrew'
$ declare -p PERSON
declare -A PERSON='([FNAME]="John" [LNAME]="Andrew" )'
$ PERSONS[1]=([FNAME]="John" [LNAME]="Andrew" )
bash: PERSONS[1]: cannot assign list to array member

適切な配列インデックス文字列を作成することで、多次元性を偽造できます。

declare -A PERSONS
declare -A PERSON

PERSON["FNAME"]='John'
PERSON["LNAME"]='Andrew'
i=1
for key in "${!PERSON[@]}"; do
  PERSONS[$i,$key]=${PERSON[$key]}
done

PERSON["FNAME"]='Elen'
PERSON["LNAME"]='Murray'
((i++))
for key in "${!PERSON[@]}"; do
  PERSONS[$i,$key]=${PERSON[$key]}
done

declare -p PERSONS
# ==> declare -A PERSONS='([1,LNAME]="Andrew" [2,FNAME]="Elen" [1,FNAME]="John" [2,LNAME]="Murray" )'
29
glenn jackman

何が必要かわかりました。何週間も同じものが欲しかった。 PythonまたはBashのどちらを使用するか混乱しました。最後に、何か他のことを調べたところ、これが見つかりました Bash:連想配列を別の変数名に割り当てる方法(変数の名前を変更するなど))?

ここで、文字列を割り当て、後でコマンドとして使用する方法を知った。それから私の創造性で私は以下のようにあなたの問題の解決策を見つけました:-


#!/bin/bash

declare -A PERSONS
declare -A PERSON

PERSON["FNAME"]='John'
PERSON["LNAME"]='Andrew'
string=$(declare -p PERSON)
#printf "${string}\n"
PERSONS["1"]=${string}
#echo ${PERSONS["1"]}

PERSON["FNAME"]='Elen'
PERSON["LNAME"]='Murray'
string=$(declare -p PERSON)
#printf "${string}\n"
PERSONS["2"]=${string}
#echo ${PERSONS["2"]}

for KEY in "${!PERSONS[@]}"; do
   printf "$KEY - ${PERSONS["$KEY"]}\n"
   eval "${PERSONS["$KEY"]}"
   printf "${PERSONS["$KEY"]}\n"
   for KEY in "${!PERSON[@]}"; do
      printf "INSIDE $KEY - ${PERSON["$KEY"]}\n"
   done
done

出力:-

1-declare -A PERSON = '([FNAME] = "John" [LNAME] = "Andrew")'

declare -A PERSON = '([FNAME] = "John" [LNAME] = "Andrew")'

FNAME内-ジョン

LNAME内-アンドリュー

2-declare -A PERSON = '([FNAME] = "Elen" [LNAME] = "Murray")'

declare -A PERSON = '([FNAME] = "Elen" [LNAME] = "Murray")'

FNAMEの内側-Elen

LNAMEの内側-マレー


実際にbashの多次元配列、特にアプローチでの問題は、PERSON配列の値を配列要素PERSONS [1]に割り当てていることです。配列要素PERSONS [1]は、割り当て時にassoc配列ではなくリストに変換されます。配列のデータ構造に関する情報を値に保持していないので、配列の2つの要素と見なされなくなりました。したがって、このハックで十分であることがわかりました。値を格納/取得するたびにこれを行う必要があるという制限は1つだけです。しかし、それはあなたの目的を解決します。

2
sameer Soni