シェルスクリプトの配列の使い方について

今回は、シェルスクリプトの配列の使い方についてご紹介します。

  • 配列の宣言・初期化
  • 配列から特定要素の値を取得する
  • 指定した Offset からの値取得、特定要素の文字長取得、及び配列の要素数取得
  • 空配列と要素を持つ配列について
  • 配列複製と要素追加
  • 内部コマンド unset を使って配列の要素を削除
  • Loop を使って配列要素出力

配列の宣言・初期化、及び配列から値を取得

配列の宣言・初期化

配列を宣言・初期化するためには、以下のようにします。

  • fruit=() のように配列を宣言する
  • fruit[0]="apple" のように 1つの要素を 1行単位で宣言・初期化する
  • fruit=([0]=apple [1]=banana [2]=orange) のように宣言・初期化する
  • fruit=(apple banana orange) のように宣言・初期化する
  • declare -a fruit=(apple banana orange) のように宣言・初期化する

declare について

最後の declare -a は、変数を配列をして宣言するという意味ですが、可読性が良くないため、特別な理由が無い限り、私はあまり使いませんが、よく使うオプションとしては以下があります。

declare -a : 変数を配列として宣言

declare -i : 数字型変数として宣言

declare -r : 読み取り専用変数として宣言

例えば、読み取り専用の数字型配列を宣言したいときには、以下のようにします。

declare -air numbers=(0 1 2 3 4)

#!/bin/bash

fruit[0]="apple"
fruit[1]="banana"
fruit[2]="orange"
fruit[3]=

sports=([0]=soccer [1]=tennis [2]=volleyball)

animal=(dog rabbit hamakuchi)

配列から特定要素の値を取得する

配列変数に格納されている特定要素の値を取得するには、${variable[xxx]} のように波括弧を使います。

#!/bin/bash

#### 配列内要素の値取得 : その1 ####
fruit[0]="apple"
fruit[1]="banana"
fruit[2]="orange"
fruit[3]=

echo "fruit[0] : ${fruit[0]}"    #### apple
echo "fruit[1] : ${fruit[1]}"    #### banana
echo "fruit[2] : ${fruit[2]}"    #### orange
echo "fruit[3] : ${fruit[3]}"    #### 初期化してないので、何も出力されない
echo "fruit[4] : ${fruit[4]}"    #### 宣言しなかったので、何も出力されない
echo

#### 配列内要素の値取得 : その2 ####
sports=([0]=soccer [1]=tennis [2]=volleyball)

echo "${sports[0]}"    #### soccer
echo "${sports[1]}"    #### tennis
echo "${sports[2]}"    #### volleyball
echo

#### 配列内要素の値取得 : その3 ####
animal=(dog cat rabbit)

echo "${animal[0]}"     #### dog
echo "${animal[1]}"     #### cat
echo "${animal[2]}"     #### rabbit

配列変数の独特な文法

少し特殊な使い方として、:@* を配列と一緒に使うことができます。

指定した Offset からの値取得、特定要素の文字長取得、及び配列の要素数取得

#!/bin/bash

numbers=(zero one two three four)

echo "${numbers[0]}"       #### zero (普通に特定要素の値取得)

echo "${numbers:0}"        #### zero (0番目要素の Offset 0 から値取得)
echo "${numbers[0]:1}"     #### ero  (0番目要素の Offset 1 から値取得)

echo "${numbers[1]:1}"     #### ne   (1番目要素の Offset 1 から値取得)

echo "${#numbers}"         #### 4    (0番目要素の文字長)
echo "${#numbers[0]}"      #### 4    (0番目要素の文字長)
echo "${#numbers[1]}"      #### 3    (1番目要素の文字長)

echo "${#numbers[@]}"      #### 5    (配列の要素数取得)
echo "${#numbers[*]}"      #### 5    (配列の要素数取得)

echo "${numbers[@]}"       #### zero one two three four (配列の要素を全て出力)
echo "${numbers[*]}"       #### zero one two three four (配列の要素を全て出力)

空配列と要素を持つ配列について

以下は、配列の宣言方法にって、配列の要素数と要素の文字列がどういうふうにカウントされるか確認する例です。

#!/bin/bash

array_a=(zero one two)
array_b=('')
array_c=("")
array_d=()

echo "array_a : ${array_a[@]}"     #### zero one two
echo "array_b : ${array_b[@]}"     #### 何も出力されない
echo "array_c : ${array_c[@]}"     #### 何も出力されない
echo "array_d : ${array_d[@]}"     #### 何も出力されない
echo
echo "array_a : ${#array_a[*]}"    #### 3 (array_a の要素数)
echo "array_b : ${#array_b[*]}"    #### 1 (array_b の要素数)
echo "array_c : ${#array_c[*]}"    #### 1 (array_c の要素数)
echo "array_d : ${#array_d[*]}"    #### 0 (array_d の要素数)
echo
echo "array_a : ${#array_a[0]}"    #### 4 (array_a の 0番目要素の文字数)
echo "array_b : ${#array_b[0]}"    #### 0 (array_b の 0番目要素の文字数)
echo "array_c : ${#array_d[0]}"    #### 0 (array_c の 0番目要素の文字数)
echo "array_d : ${#array_d[0]}"    #### 0 (array_d の 0番目要素の文字数)

上記の結果 Line: 14、15 を見れば分かるように、空配列 ' '" " も要素数としてカウントされますが、文字列としてはカウントされません。

配列複製と要素追加

以下の例では、numbers 配列をコピーした上で、numbers_copied 配列に要素 two と three を追加します。

#!/bin/bash

numbers=(zero one)                   #### 配列宣言

numbers_copied=("${numbers[@]}")     #### 配列複製
numbers_copied=("${numbers_copied[@]}" "two")      #### 複製した配列に @ を使って要素追加
numbers_copied=("${numbers_copied[*]}" "three")    #### 複製した配列に * を使って要素追加

echo "${numbers[@]}"                 #### zero one
echo "${numbers_copied[@]}"          #### zero one two three
echo "${numbers_copied[*]}"          #### zero one two three

内部コマンド unset を使って配列の要素を削除

内部コマンド unset は、変数に NULL をセットして空っぽ状態にする時に使うコマンドですが、これを配列に使うと配列のある要素を削除したり、配列要素全体を削除することができます。

#!/bin/bash

colors=(white red black)

echo "${#colors[@]}"       #### 3
echo "${colors[@]}"        #### white red black
echo

unset colors[0];           #### 配列の 1番目の要素を削除

echo "${#colors[@]}"       #### 2
echo "${colors[@]}"        #### red black
echo

unset colors;              #### 配列要素を全て削除

echo "${#colors[@]}"       #### 0
echo "${colors[@]}"        #### 空っぽなので、何も出力されない

Tip: 配列要素全体を削除する際に使った unset colors; は、以下のような使い方も可能です。

unset colors[*];

unset colors[@];

配列要素出力

Loop しながら配列の要素を全て出力するためには、以下のようにします。

#!/bin/bash

numbers=(zero one two three four)

for i in ${numbers[@]}
do
    echo $i
done
$ ./numbers.sh
zero
one
two
three
four

終わりに

メンテナンス・可読性を考えるとシェルスクリプトで配列を使うべきか悩ましいところですが、リソース管理が必要だったり、高度な処理が必要な場合には、C とか Perl とか他の言語を使った方が良い気がしますが、状況に応じて使ってみてください。

以上、シェルスクリプトで配列を扱うための基礎知識でした。