29
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-03-15

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の連想配列が使えるので、試してみてください!

29
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?