それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

bashで連想配列(assoc array / hash ) を使う。

bash の配列にも 連想配列が加わりました。

追加されたバージョンは、bash 4.2 からです。

はじめに連想配列とは何なのか

連想配列PHPでの略語)は associative array と呼ばれる機能です。js や php を始めスクリプト系言語ではおなじみですね。

# javascript連想配列(オブジェクト)
obj = {}
obj["name"] = "takuya"
# php連想配列(array)
$arr = []
$arrj["name"] = "takuya"

このように、配列のインデックスに「文字列」を使うことで柔軟な記述とプログラミングができるようになるのが、Associative Arrayです。

他の言語では hashdict などとも呼ばれます。

bash連想配列の機能について

bash にも配列の機能があります。この機能で連想配列が使えるようになっています。

debian lenny や ubuntu 最新版であれば bash 4 になっているんので安心して試すことが出来ます。

bash4 以前では使えません。たとえばMac OSX のデフォルトbash は 3.54 なので使えません。

OSX el capitan の場合は brew install bash が必要でした。

Bash連想配列の書き方

連想配列の書き方は、bash の配列の書きかたとほとんど同じなので、慣れている人は変数宣言してしまえば、特に気にせず使えると思います。

連想配列の宣言方法

連想配列を使うには、変数を連想配列として宣言する必要があります。 declare で変数を宣言するときに -A のオプションが必要です。

# 連想配列の変数宣言の例
declare -A MY_ARRAY

連想配列とキー

キーとなるStringを使ってアクセスします。

連想配列のキーに文字列を指定して、データを格納していきます。この辺はどの言語でも同じなので使うには困りません。

# 連想配列に値を格納する例
MY_ARRAY[name]=takuya

連想配列から値を取り出すのは、bash の配列アクセスとほぼ同じです。

# 連想配列から値を取り出す例
echo ${MY_ARRAY[name]} #=> takuya

配列の長さ

配列の長さも、bash の配列と同じです。 ${#array[@]} または ${#array[*]} でアクセスします。

# 連想配列の長さを取得する例
declare -A MY_ARRAY
MY_ARRAY[name]=takuya
MY_ARRAY[id]=0001

echo ${#MY_ARRAY[@]} #=> 2

配列のキーと値を扱う。

連想配列に、キーと値を入れた場合、これをループで回さないと意味がないですよね。配列はループで使って役に立つわけですしね。

配列のキーの一覧を取り出して中身を見てみましょう

## 配列のキーの一覧を取り出す例
echo ${!MY_ARRAY[@]}
# または
echo ${!MY_ARRAY[*]}

連想配列のキーの一覧を取り出してしまえば、あとはループで回せばいいわけです。

## 連想配列のfor ループの例
for key in  ${!MY_ARRAY[*]} ; do echo $key = ${MY_ARRAY[$key]} ; done
id = 0001
name = takuya

for .. in ループを使って、連想配列のキーを取り出し、キーを変数key に格納し、連想配列にアクセスします。

これで、連想配列で二次元配列を作ったりしてKey-Valueが使えるようになりました。

連想配列の要素を消す。

今度は、要素を削除する方法を知っておきたいと思います。要素を削除できるようになりましょう。

変数の削除に unset を使うのですが、連想配列の要素の削除にも unset が使えます。

# 連想配列の要素を削除する例
unset -v MY_ARRAY[name]

そして、変数自体が要らなくなった場合にも unset ですね。

# 連想配列を削除する例
unset -v MY_ARRAY

最後に

これで、一通り使えるようになりました。

新機能を覚えておけばBash がさらに便利になると思います。

bashシェルスクリプトはどこで使うのと思うかもしれません。しかし、bashrc を書くには bash の機能を知っておくのが一番いいのです。

まさかbash 用のbashrc をPOSIX準拠で書く人はいませんね。

また、bash はどこでも使えるデフォルトシェルです。最初から入っているので低機能だとか古めかしと思われがちですが、bash もやはり進化しているのです。

最後におさらい

bash連想配列の機能をひと目で分かるようにまとめておきます。

declare -A MY_ARRAY
MY_ARRAY[name]=takuya
MY_ARRAY[id]=0001

echo length is  ${#MY_ARRAY[@]} #=> 2

echo show assoc array entries


for key in  ${!MY_ARRAY[*]} ; do 
  echo $key = ${MY_ARRAY[$key]} ;
done


unset -v MY_ARRAY[name]
unset -v MY_ARRAY[id]
unset -v MY_ARRAY

連想配列機能について

Bash Hackers Wiki の記述の邦訳を書いておきました。

Associative arrays (sometimes known as a "hash" or "dict") use arbitrary nonempty strings as keys. In other words, associative arrays allow you to look up a value from a table based upon its corresponding string label. Associative arrays are always unordered, they merely associate key-value pairs. If you retrieve multiple values from the array at once, you can't count on them coming out in the same order you put them in. Associative arrays always carry the -A attribute, and unlike indexed arrays, Bash requires that they always be declared explicitly (as indexed arrays are the default, see declaration). Associative arrays were first introduced in ksh93, and similar mechanisms were later adopted by Zsh and Bash version 4. These three are currently the only POSIX-compatible shells with any associative array support.

Associative arrays( Hash や Dict とも呼ばれる)機能は、任意の文字列(空文字以外)をキーに配列に格納します。いわば、associative arrays によって表における各行に列の<見出し文字列>でアクセスできるようになるものです。associative arrays内部には基本的に順番はありません。つまり単なるKey-Valueストアです。配列から一度にデータを取り出すとき、保存した順で取り出せるとは限りません。associative arraysは、いつも -A を使ってアクセスします。通常の配列インデックスの数字を使うときとの大きな違いです。associative arraysは ksh93 で初めて世に出てきました。そして、その同等機能が、zsh にも、そしてbash4 でも採用されました。そのため、ksh/zsh/bashPOSIX準拠シェルでassociative arraysをサポートしています。

まとめ・ポイント

連想配列が使えるのは次の3つ - ksh - zsh - そして bash 4.

連想配列-Aを使って宣言する。

連想配列は、'' の空文字をキーに出来ない。

配列と使い方は同じ。

TODO:ユニコードサポートを意識すれば日本語も使える??

参考資料