【じぶんメモ】シェルスクリプトで配列を使ってみる(配列操作)


Alfredのワークフローで遊んでいます。スクリプトにzshを利用しているのですが、シェルスクリプト初心者なので自分のためにメモを残します

シェルスクリプトで配列を使ってみる(配列操作)

要素のループ参照

添字の数字でループする方法と、直接要素をループする方法があります
添字を計算して利用するようなことがなければ、後者での利用が直感的でわかりやすいかも

 # 1から3をxに代入して、xを添字として利用
array=(One Two Three); for x in {1..3}; do echo 'array['$x']='$array[x]; done
 #=> array[1]=One
 #=> array[2]=Two
 #=> array[3]=Three

 # 要素をxに代入して、そのまま利用(添字のない$xをエコーしている部分に注目!)
array=(One Two Three); for x in $array; do echo x=$x; done
 #=> x=One
 #=> x=Two
 #=> x=Three

配列に要素を追加する

後ろに追加するには、括弧の中を、配列、区切り文字(空白)、追加項目とします
配列を展開して、末尾に項目を追加するイメージです
配列=($配列 追加項目)

足し算みたいな書き方もOK
配列+=(追加項目)

 # 後ろに追加する場合
array=(One Two Three); array=($array Four); for x in {1..4}; do echo 'array['$x']='$array[x]; done
 #=> array[1]=One
 #=> array[2]=Two
 #=> array[3]=Three
 #=> array[4]=Four

 # 足し算をするみたいに追加することもできます!目から鱗ですね
array=(One Two Three); array+=(Four); for x in {1..4}; do echo 'array['$x']='$array[x]; done
 #=> array[1]=One
 #=> array[2]=Two
 #=> array[3]=Three
 #=> array[4]=Four

では、先頭に追加する場合はどうでしょう
簡単ですね、追加したい要素の後に配列を展開すればOKです
配列=(追加項目 $配列)

 # 追加項目、区切り文字(空白)、配列という書き方です
array=(One Two Three); array=(Zero $array); for x in {1..4}; do echo 'array['$x']='$array[x]; done
 #=> array[1]=Zero
 #=> array[2]=One
 #=> array[3]=Two
 #=> array[4]=Three

配列から要素を削除する

先頭項目の削除はshift命令で可能
shift 配列

末尾の削除は位置指定で、最初から末尾2つ目の項目までを展開すればOK
マイナス指定ができるので便利ですね
配列=($配列[1,-2])

途中の項目も配列の要素指定ができるので簡単ですね
n個目の項目を削除する場合
配列=($配列[1,n-1] $配列[n+1,-1])

 # 先頭を削除
array=(One Two Three); shift array; for x in {1..3}; do echo 'array['$x']='$array[x]; done
 #=> array[1]=Two
 #=> array[2]=Three
 #=> array[3]=

 # 最後を削除
array=(One Two Three); array=($array[1,-2]); for x in {1..3}; do echo 'array['$x']='$array[x]; done
 #=> array[1]=One
 #=> array[2]=Two
 #=> array[3]=

 # 3つ目を削除
array=(One Two Three Four Five);array=($array[1,2] $array[4,5]);for x in {1..5}; do echo 'array['$x']='$array[x]; done
array[1]=One
array[2]=Two
array[3]=Four
array[4]=Five
array[5]=

 # おまけ。4つ目を四に変更
array=(One Two Three Four Five);array=($array[1,3] 四 $array[5]);for x in {1..5}; do echo 'array['$x']='$array[x]; done
 #=> array[1]=One
 #=> array[2]=Two
 #=> array[3]=Three
 #=> array[4]=四
 #=> array[5]=Five

シェルスクリプトで連想配列を使ってみる

添字を文字列で扱う連想配列も利用できますが、事前にtypeset宣言が必要です

連想配列の宣言
typeset -A 配列
連想配列のセット
配列[キー]=値

 #添字をひとつずつ指定してセットする場合
unset array; typeset -A array; array[hi]=One; array[fu]=Two; array[mi]=Tree;for x in ${(k)array[@]}; do echo 'array['$x']='${array[$x]}; done
 #=> array[hi]=One
 #=> array[mi]=Tree
 #=> array[fu]=Two

 # 一括でセットする場合、キーと値を下記のように指定します。ちなみに宣言と同時にセットしています
typeset -A array=([hi]=One [fu]=Two [mi]=Tree); for x in ${(k)array[@]}; do echo 'array['$x']='${array[$x]}; done
 #=> array[hi]=One
 #=> array[mi]=Tree
 #=> array[fu]=Two

既に上記の例で表示する際に使っていますが、
ループに必要なキーの展開は${(k)配列名[@]}となります
あれれ、順番が変わっていますね

雑談

連想配列で遊んでみました
連想配列も、普通の配列と同様に1次元なので使いにくいですね

JSONみたいなデータを連想配列にしてみました
何かに使えるかも
添字は日本語でもできますね

PCという連想配列に下記のキーと値をセットする例です

キー
機種 MacbookAir
OS Monterey
チップ M1
メモリ 8GB
ディスプレイ Retina 13.3インチ
ストレージ SSD 500GB
unset PC;typeset -A PC; PC=([機種]=MacbookAir [OS]=Monterey [チップ]=M1 [メモリ]=8GB [ディスプレイ]='Retina 13.3インチ'  [ストレージ]='SSD 500GB');  for x in ${(k)PC}; do echo 'PC['$x']='${PC[$x]}; done
 #=> PC[ストレージ]=SSD 500GB
 #=> PC[OS]=Monterey
 #=> PC[メモリ]=8GB
 #=> PC[チップ]=M1
 #=> PC[ディスプレイ]=Retina 13.3インチ
 #=> PC[機種]=MacbookAir

今度は、連想配列のキーを数字にしてみました
意味ないか

unset array;typeset -A array=([1]=One [2]=Two [3]=Tree);  for x in {1..3}; do echo 'array['$x']='$array[$x]; done
 #=> array[1]=One
 #=> array[2]=Two
 #=> array[3]=Three