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

:::note info
Alfredのワークフローなどで、スクリプトにzshをはじめました。初心者用にメモを残します
:::

# シェルスクリプトで配列を使ってみる（配列操作）

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

```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
``` 配列+=(追加項目)```
```zsh
 # 後ろに追加する場合
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です
```配列=(追加項目 $配列)```

```zsh
 # 追加項目、区切り文字（空白）、配列という書き方です
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])```

```zsh
 # 先頭を削除
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 配列```
連想配列のセット
```配列[キー]=値```


```zsh
 #添字をひとつずつ指定してセットする場合
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

```zsh
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
```

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

```zsh
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

```