Zsh

zshの連想配列の使い方まとめ

More than 3 years have passed since last update.

zshでは連想配列が使える。でも、普通のプログラム言語と違ってちょっと癖があるので、ここで使い方についてまとめてみる。


宣言

連想配列は必ずtypesetかlocalで宣言が必要になる。typeset -Aまたはlocal -Aという形で宣言する。

# ローカル変数として宣言する

local -A hash1
# または
typeset -A hash2

# グローバル変数として宣言する

typeset -g -A hash1

連想配列に限らないことだけど、関数の中でtypesetで宣言した場合は関数内のローカル変数になる。typesetで宣言しつつグローバル変数にしたい場合は-gオプションを付ける。


代入

連想配列全体に値を代入するには、カッコでくくって、「キー」「値」の順にスペース区切りで並べて書く。

typeset -A user1

user1=(id 13 name mollifier address Kobe)
# { id => 13, name => mollifier, address => Kobe } という連想配列になる

# カッコだけ書くと空の連想配列になる
typeset -A empty_hash
empty_hash=()


要素の参照

連想配列の各要素を参照する方法はこんな感じ。

typeset -A user1

user1=(id 13 name mollifier address Kobe)

echo $user1[id] #=> 13
echo $user1[name] #=> mollifier

# {}で囲っても良い
echo ${user1[address]} #=> Kobe

要素全体を参照する方法は以下。

# [@]または[*] で値全体の配列になる

echo $user1[@] #=> Kobe 13 mollifier
echo $user1[*] #=> Kobe 13 mollifier

# [@]と[*]は"で囲んだときに違いが出る
# [@]は各要素がそれぞれ"で囲まれる
# [*]は要素全体が"で囲まれて一つの文字列になる(echoでは違いがわからないけど)
echo "$user1[@]" #=> "Kobe" "13" "mollifier"
echo "$user1[*]" #=> "Kobe 13 mollifier"

# $user1[*]は省略して$user1と書ける
echo $user1 #=> Kobe 13 mollifier

# (k)を付けると、すべてのキーを含む配列になる
echo ${(k)user1} #=> address id name

# (kv)を付けると、キー、値、と順に並べた配列になる
echo ${(kv)user1} #=> address Kobe id 13 name mollifier

# 要素数(キー/値の組の数)も取得できる
echo ${#user1} #=> 3


追加、変更、削除

キーを指定して値の追加、変更、削除ができる。

typeset -A user1

user1=(id 13 name mollifier address Kobe)
# この時点では { id => 13, name => mollifier, address => Kobe }

# 追加
user1[age]=17
# この時点 { id => 13, name => mollifier, address => Kobe, age => 17 } になる

# 変更
# すでに存在するキーに対して値を代入すると、値の変更になる
user1[age]=27
# この時点 { id => 13, name => mollifier, address => Kobe, age => 27 } になる

# 要素の削除("で囲む必要があることに注意)
unset "user1[address]"
# この時点 { id => 13, name => mollifier, age => 27 } になる


ループ

ループしたいときは、${(k)連想配列名}のかたちですべてのキーを取り出してそれでループする。

typeset -A user1

user1=(id 13 'super name' 'super mollifier' address Kobe)

for key in ${(k)user1}; do
echo "$key => $user1[$key]"
done
# 出力
# super name => super mollifier
# address => Kobe
# id => 13
#
# キーや値に空白が入っていても大丈夫


キーを持つかどうかのチェック

${連想配列名[(i)キー名]}という形で、「キー名」にマッチするキーが文字列として取得できる。もしキーが見つからなかったら空文字列になる。これで、連想配列に特定のキーが含まれているかどうかがチェックできる(他の言語でいうところのhas_keyのようなやつ)。

typeset -A user1

user1=(id 13 name mollifier empty '' address Kobe)

# 指定したキーが含まれる場合
if [[ -n "${user1[(i)id]}" ]]; then
echo "user1 has id"
else
echo "user1 doesn't have id"
fi
#=> user1 has id

# 指定したキーが含まれない場合
if [[ -n "${user1[(i)hoge]}" ]]; then
echo "user1 has hoge"
else
echo "user1 doesn't have hoge"
fi
#=> user1 doesn't have hoge

# 値が空文字列でもキーが存在するかどうかがチェックできる
if [[ -n "${user1[(i)empty]}" ]]; then
echo "user1 has empty"
else
echo "user1 doesn't have empty"
fi
#=> user1 has empty

この(i)は、代わりに(I)と書いても同じ意味になる。

こんな感じでzshの連想配列が使えるので、試してみてください!