bashで連想配列

## 連想配列のセット
### 連想配列宣言
変数を連想配列として扱うには、変数宣言で`-A`オプションを利用します。

```shell:連想配列の宣言
declare -A musics
```

### 初期セット
連想配列の宣言と同時に連想配列のセットも同時に行う場合は`()`で囲みます。

```shell:連想配列初期セット
declare -A musics=(
        ["ultra soul"]="2001"
        ["OCEAN"]="2005"
        ["BANZAI"]="2004"
        ["RED"]="2015"
        ["GIFT"]="2008"
)
```

### 連想配列の追加

連想配列の追加は以下のような指定します。

```shell:連想配列追加
musics["ARIGATO"]="2004"
```

### 連想配列の値変更

連想配列の値を変更する場合は、追加と同じ書き方になります。

```shell:連想配列の値変更
declare -A musics=(
        ["OCEAN"]="2006"
)
musics["OCEAN"]="2005"
```

### 連想配列の削除

連想配列に設定したものを削除する場合は、`unset`を利用します。

```shell:連想配列の削除
unset musics["GIFT"]
```

## 連想配列の表示
### 指定したキーの値を取得

連想配列から指定したキーの値を取得する場合は`${連想配列変数["キー"]}`のように指定します。

```shell:指定したキーの値を取得
echo "${musics["ultra soul"]}"
```

### 設定されている配列数を数える

連想配列に設定されている配列の数を数える場合は`${#連想配列変数[@]}`のようにします。

```shell:指定したキーの値を取得
echo "count:${#musics[@]}"
```

### キーが存在しているか確認

連想配列に指定したキーが存在するか確認する場合は、`if`文に`-n`オプションまたは`-z`オプションを利用してキーを利用して連想配列から取り出せるかを確認します。

```shell:キーが存在する場合処理
declare -A musics=(
        ["ultra soul"]="2001"
)

if [ -n "${musics["ultra soul"]}" ]; then
    echo "exist"
fi
if [ -n "${musics["GIFT"]}" ]; then
    echo "not exist"
fi

# existのみが表示される
```

```shell:キーが存在しない場合処理
declare -A musics=(
        ["ultra soul"]="2001"
)

if [ -z "${musics["ultra soul"]}" ]; then
    echo "exist"
fi
if [ -z "${musics["GIFT"]}" ]; then
    echo "not exist"
fi

# not existのみが表示される
```


## 連想配列ループ
### キーを表示する

連想配列にセットされているキーをループして表示する。
`${!連想配列名[@]}`を利用します。

```shell:キーを表示
declare -A musics=(
        ["ultra soul"]="2001"
        ["OCEAN"]="2006"
)

for music in "${!musics[@]}"; do
    echo "${music}"
done

# 処理結果
# ultra soul
# OCEAN
```

### 値を表示する

連想配列にセットされている値をループして表示する。
`${連想配列名[@]}`を利用します。`!マーク`をつけないのがポイントです。

```shell:キーを表示
declare -A musics=(
        ["ultra soul"]="2001"
        ["OCEAN"]="2006"
)

for music in "${musics[@]}"; do
    echo "${music}"
done

# 処理結果
# 2001
# 2006
```

### キーと値を同時に表示する

連想配列にセットされているキーと値のセットを同時に表示する場合は、キーを表示する時のループを利用して取り出します。

```shell:キーを表示
declare -A musics=(
        ["ultra soul"]="2001"
        ["OCEAN"]="2006"
)

for music in "${!musics[@]}"; do
    echo "${music}:${musics[${music}]}"
done

# 処理結果
# ultra soul:2001
# OCEAN:2005
```

## 上記全てをまとめた結果

以上で終わりですが、上記をまとめたshellを乗せておきます。

```shell
#!/bin/bash

# set
declare -A musics=(
	["ultra soul"]="2001"
	["OCEAN"]="2006"
	["BANZAI"]="2004"
	["RED"]="2015"
	["GIFT"]="2008"
)

musics["ARIGATO"]="2004"
musics["OCEAN"]="2005"
unset musics["GIFT"]

# read
echo "${musics["ultra soul"]}"
echo "count:${#musics[@]}"

echo "# -n option"
if [ -n "${musics["ultra soul"]}" ]; then
    echo "exist"
fi
if [ -n "${musics["GIFT"]}" ]; then
    echo "not exist"
fi

echo "# -z option"
if [ -z "${musics["ultra soul"]}" ]; then
    echo "exist"
fi
if [ -z "${musics["GIFT"]}" ]; then
    echo "not exist"
fi

# for
echo "# for key loop"
for music in "${!musics[@]}"; do
    echo "${music}"
done

echo "# for value loop"
for music in "${musics[@]}"; do
    echo "${music}"
done

echo "# for key/value loop"
for music in "${!musics[@]}"; do
    echo "${music}:${musics[${music}]}"
done
```

```console:実行結果
2001
count:5
# -n option
exist
# -z option
not exist
# for key loop
OCEAN
ARIGATO
BANZAI
ultra soul
RED
# for value loop
2005
2004
2004
2001
2015
# for key/value loop
OCEAN:2005
ARIGATO:2004
BANZAI:2004
ultra soul:2001
RED:2015
```