連想配列から無効な値を取得しましたか?

連想配列から無効な値を取得しましたか?

私は「Bash Pocket Reference」の本を読んで、連想配列に関するセクションを読んだ。ここで本のサンプルコードを試してみると、予期しない答えが得られました。

istanev@inspiron5559:~$ data=([joe]=30 [mary]=25)
istanev@inspiron5559:~$ echo ${data[joe]}
25
istanev@inspiron5559:~$ echo ${data[mary]}
25

data[joe]は30を返すべきではありませんか?なぜ25を返すのですか?私のbashバージョンは4.3.46(1)リリースです。

答え1

デフォルトでは、bashは配列をインデックス配列として扱います。
この場合、インデックスは算術式として評価されます。

$ joe=3    mary=6
$ unset data
$ data=([joe]=111 [mary]=bbb)
$ declare -p data
declare -a data=([3]="111" [6]="bbb")

出力には、次のようないくつかの点が表示されます。

  • 配列は-a出力からインデックス付けされます。
  • 配列には2つの値が含まれています。
  • joe値のインデックスは変数sumの数値と一致しますmary
  • 配列に含まれる値は文字列です。

これは、インデックスが引用されている場合でも同様です(単一引用符でも)。

$ joe=3    mary=6
$ unset data
$ data=(["joe"]=111 ["mary"]=bbb)
$ declare -p data
declare -a data=([3]="111" [6]="bbb") 

インデックスとして使用される文字列が数値を含むように定義されていない場合は、とにかく値が0の算術式として評価されます。

$ unset joe    ;    unset mary    ;    unset data
$ data=([joe]=111 [mary]=bbb)
$ declare -p data
declare -a data=([0]="bbb")

[joe]=111評価結果はで、[0]=111インデックスの配列0はに設定されます111。ただし、と[mary]=bbb評価され、[0]=bbbindexの配列値がに置き換え0られますbbb

実際に連想配列を持つには、使用する前に定義する必要があります。
データが含まれている間は変更できません。配列の設定は次のとおりです。

$ declare -A data
bash: declare: data: cannot convert indexed to associative array

ただし、これを消去するには、次のようにします。

$ joe=3  ;  mary=6  ; unset data

$ declare -A data

$ data=([joe]=111 [mary]=bbb)
$ declare -p data
declare -A data=([joe]="111" [mary]="bbb" )

ご覧のとおり、インデックスとして使用される文字列も有効な変数名であり、値が含まれているかどうかは重要ではありません。連想配列の文字列インデックスとして使用されます。

答え2

typeset -A連想配列は、またはそれに対応する(declare -Aまたはreadonly -Abashで)使用して明示的に宣言する必要があります。デフォルトでは、配列は整数インデックスを持つ「一般」配列です。整数インデックス配列の非数値インデックスは算術式として解釈され、算術式で設定されていない変数名はデフォルトでゼロと解釈されるため、data=([joe]=30 [mary]=25)set data[0]=30、then data[0]=25${data[whatever]}is要素は0、つまりです25

bash-4.3$ indexed=([a]=aye [b]=bee [x+1]=cee)
bash-4.3$ echo length=${#indexed[@]} a=${indexed[a]} b=${indexed[b]} x+1=${indexed[x+1]} 1=${indexed[1]}
length=2 a=bee b=bee x+1=cee 1=cee
bash-4.3$ typeset -A associative=([a]=aye [b]=bee [x+1]=cee)
bash-4.3$ echo length=${#associative[@]} a=${associative[a]} b=${associative[b]} x+1=${associative[x+1]} 1=${associative[1]}
length=3 a=aye b=bee x+1=cee 1=

なぜならindexed、それは数値インデックスを持つ配列であり、indexed[a]そしてはindexed[b]すべてであるからです。連想配列の場合、角かっこ内の内容は文字列として解析されます(通常は二重引用符で拡張されるため、書き込むことができます)。indexed[0]indexed[x+1]indexed[1]${associative[$key]}

関連情報