シェルスクリプトに挑戦しよう(18)連想配列“応用力”をつけるためのLinux再入門(38)

今回で「配列」は最終回となります。今回のテーマは、bashのバージョン4以降から使用できるようになった「連想配列」です。

» 2019年06月05日 05時00分 公開
[西村めぐみ@IT]
「“応用力”をつけるためのLinux再入門」のインデックス

“応用力”をつけるためのLinux再入門

連想配列とは?

 bashでは、バージョン4以降から「連想配列(Associative arrays)」が使用できるようになりました。

 通常の配列では、今まで見てきたように添字は数値で指定しますが、連想配列の場合は文字列も使用できるようになります。本連載では、連想配列は添字ではなく「キー」と呼ぶことにします。

 連想配列の場合、「declare -A 配列名」で事前に配列を定義してから使用します()。例えば、「exam」という名前の連想配列であれば、「declare -A exam」のように指定します。

【※】通常の配列の場合は「declare -a 配列名」で定義します。配列ではない変数を事前に定義してから使用したい場合は「declare 変数名」とします。



 個々の値は「配列名[キー]=値」のようにセットします。例えば、「exam」という連想配列において、「suzuki」に対し「80」をセットするのであれば、「exam["suzuki"]=80」のようにします。引用符を省略して「exam[suzuki]=80」のように指定することも可能です。

 値の参照は、通常の配列同様、$と{}を付けて、「${exam["suzuki"]}」のようにします。ここでも引用符は省略できます。

declare -A exam		(連想配列「exam」を定義する)
▲コマンド例
exam[suzuki]=80
exam["suzuki"]=80
exam['suzuki']=80
▲連想配列「exam」で、suzukiに80をセットする(全て同じ動作となる)
echo ${exam[suzuki]}
echo ${exam["suzuki"]}
echo ${exam['suzuki']}
▲連想配列「exam」で、suzukiの値を表示する(全て同じ動作となる)

 「for 〜 in」で配列の値を全て参照したい場合も、通常の配列同様、「for 変数名 in ${配列名[@]}」のようにします。

 全てのキーの値を参照したい場合は、配列名の前に「!」記号を付けて、「for 変数名 in ${!配列名[@]}」のようにします。

 以下のサンプルスクリプト(arraytest)では、連想配列「exam」を定義し、suzuki、tanaka、yamamotoの点数を保存しています。そして、1つ目のfor文では全員の点数を順次表示し、2つ目のfor文では全員の名前と点数(キーと値)を表示しています。なお、サンプルスクリプトでは、suzukiが連想配列のキーであることを分かりやすくするために、キーに引用符を使用しています。

#! /bin/bash
declare -A exam
exam["suzuki"]=80
exam["tanaka"]=95
exam["yamamoto"]=90
for e in ${exam[@]} 
do 
  echo $e
done
for k in ${!exam[@]}
do
  echo "key  : $k"
  echo "value: ${exam[$k]}"
done
▲スクリプト「arraytest」
$ chmod +x arraytest
$ ./arraytest
95
80
90
key  : tanaka
value: 95
key  : suzuki
value: 80
key  : yamamoto
value: 90
▲「arraytest」の実行結果

 参考までに、「arrray -A exam」ではなく「array -a exam」、つまり通常の配列として定義した場合の実行結果は以下のようになります。

$ ./arraytest
90			← exam[0]に、最後にセットした80が保存されている
key  : 0
value: 90
▲「array -a exam」とした場合の実行結果

 exam["suzuki"]、exam["tanaka"]、exam["yamamoto"]が、全て「exam[0]」となっているため、最後にセットした「90」だけが表示されています(本連載 第37回「添字の変数に数値以外をセットした場合」参照)。

●連想配列の値を変更する

 連想配列に対し、既存のキーを指定して値をセットした場合は「値の変更」、新しいキーを指定して値をセットした場合は「値の追加」となります。

echo "==change=="
exam["suzuki"]=85	#キー"suzuki"の値の変更
exam["sakai"]=75	#キー"sakai"と値を追加
#内容確認
for k in ${!exam[@]}
do
  echo "key  : $k"
  echo "value: ${exam[$k]}"
done
▲スクリプト(arraytestに追加)
95
80
90
key  : tanaka
value: 95
key  : suzuki
value: 80
key  : yamamoto
value: 90
==change==
key  : tanaka
value: 95
key  : sakai			← キー「sakai」が追加されている
value: 75
key  : suzuki
value: 85				← キー「suzuki」の値が変更されている
key  : yamamoto
value: 90
▲実行結果

●連想配列に値をまとめてセットする

 連想配列に値をまとめてセットする場合は、「配列名=([キー]=値 [キー]=値)」のように、キーと値のペアで指定します。

 この書き方で値を追加したい場合は、「+=」を使って「配列名+=([キー]=値 [キー]=値)」のようにします。

#examを連想配列として定義
declare -A exam
#examに値をセット
exam=(["suzuki"]=80 ["tanaka"]=95 ["yamamoto"]=90)
#内容確認
for k in "${!exam[@]}"
do
  echo $k ${exam[$k]}	#キーと値を表示
done
▲スクリプト例(値をまとめてセット)
#examに値を追加
exam+=(["suzuki"]=85 ["sakai"]=75)
#内容確認
for k in "${!exam[@]}"
do
  echo $k ${exam[$k]}
done
▲スクリプト例(値を追加)

 以下の実行結果ではコマンドラインで全て入力しているので、引用符を省略しています。

$ declare -A exam
$ exam=([suzuki]=80 [tanaka]=95 [yamamoto]=90)
$ for k in ${!exam[@]}
> do
> echo $k ${exam[$k]}
> done
tanaka 95
suzuki 80
yamamoto 90
$ exam+=([suzuki]=85 [sakai]=75)
$ for k in ${!exam[@]}
> do
> echo $k ${exam[$k]}
> done
tanaka 95
sakai 75			← キー「sakai」が追加されている
suzuki 85			← キー「suzuki」の値が変更されている
yamamoto 90
▲実行結果

●連想配列のコピー

 連想配列の場合、個々のキーと値をコピーする必要があります。なお、この方法は連想配列ではない通常の配列にも使用できます。

declare -A signal       #signalを連想配列として定義
declare -A mysignal     #mysignalを連想配列として定義
#signalに値をセット
signal["NG"]="red"
signal["OK"]="green"
#mysignalにsignalをコピー
for i in ${!signal[@]}; do
  mysignal[$i]=${signal[$i]}
done
▲スクリプト例(連想配列のコピー)
echo ${signal[@]}	#signalの値(redとgreen)が表示される
echo ${mysignal[@]}	#上と同じ内容が表示される
echo ${!signal[@]}	#signalのキー(NGとOK)が表示される
echo ${!mysignal[@]}	#上と同じ内容が表示される
echo ${mysignal["NG"]}	#「red」が表示される
echo ${mysignal["OK"]}	#「green」が表示される
▲実行結果
declare -a week		#weekを配列として定義(省略可能)
declare -a myweek	#myweekを配列として定義(省略可能)
week=(Sun Mon Tues Wed Thur Fri Sat)
#配列のコピー
for i in ${!week[@]}; do
  myweek[$i]=${week[$i]};
done
▲スクリプト例(通常の配列)
echo ${week[@]}
echo ${myweek[@]}
▲実行結果

筆者紹介

西村 めぐみ(にしむら めぐみ)

もともとはDOSユーザーで「DOS版UNIX-like tools」を愛用。ソフトハウスに勤務し生産管理のパッケージソフトウェアの開発およびサポート業務を担当、その後ライターになる。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。地方自治体の在宅就業支援事業にてMicrosoft Officeの教材作成およびeラーニング指導を担当。会社などの“PCヘルパー”やピンポイント研修なども行っている。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。