今回で「配列」は最終回となります。今回のテーマは、bashのバージョン4以降から使用できるようになった「連想配列」です。
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
echo ${exam[suzuki]}
echo ${exam["suzuki"]}
echo ${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
$ chmod +x arraytest $ ./arraytest 95 80 90 key : tanaka value: 95 key : suzuki value: 80 key : yamamoto value: 90
参考までに、「arrray -A exam」ではなく「array -a exam」、つまり通常の配列として定義した場合の実行結果は以下のようになります。
$ ./arraytest 90 ← exam[0]に、最後にセットした80が保存されている key : 0 value: 90
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
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.