配列(array)
| 対応: | 全Linux | |
|---|---|---|
| macOS(2001 Cheetah) | ||
| Bash 2.0(1996) |
Bashの配列は、複数の値をひとつの変数にまとめて管理するデータ構造です。インデックス(番号)で要素を区別するインデックス配列と、文字列キーで区別する連想配列の2種類があります。連想配列はBash 4.0以降で使用できます。
構文
インデックス配列を定義するには、括弧内に要素をスペース区切りで並べます。
arr=(要素1 要素2 要素3)
インデックスを指定して個別に代入することもできます。
arr[0]=要素1 arr[1]=要素2
連想配列を定義するには、あらかじめ declare -A で宣言してからキーと値を代入します。
declare -A assoc assoc[キー]=値
特定のインデックスを参照するには ${arr[インデックス]} を使います。すべての要素を取得するには ${arr[@]} または ${arr[*]} を使います。
${arr[0]} # インデックス0の要素
${arr[@]} # 全要素(各要素を別々の引数として展開)
${arr[*]} # 全要素(IFS区切りの1つの文字列として展開)
${#arr[@]} # 要素数
${!arr[@]} # 全インデックス(キー)
${arr[@]:start:length} # スライス(start番目からlength個)
要素を追加するには += を使います。要素を削除するには unset を使います。
arr+=(新要素) # 末尾に追加 unset arr[インデックス] # 指定要素を削除
操作一覧
| 操作 | 書き方 | 概要 |
|---|---|---|
| インデックス配列の定義 | arr=(a b c) | 括弧内にスペース区切りで要素を並べます。 |
| 個別代入 | arr[0]=a | インデックスを指定して要素を代入します。 |
| 連想配列の宣言 | declare -A assoc | 連想配列として宣言します。Bash 4.0以降が必要です。 |
| 要素の参照 | ${arr[0]} | 指定インデックスの要素を取得します。 |
| 全要素の展開 | ${arr[@]} | 全要素を個別の引数として展開します。 |
| 要素数の取得 | ${#arr[@]} | 配列内の要素数を返します。 |
| 全インデックスの取得 | ${!arr[@]} | 全インデックス(キー)を展開します。 |
| 要素の追加 | arr+=(d) | 末尾に要素を追加します。 |
| 要素の削除 | unset arr[1] | 指定インデックスの要素を削除します。 |
| スライス | ${arr[@]:1:2} | インデックス1から2個の要素を取得します。 |
| ループ処理 | for item in "${arr[@]}" | 全要素をひとつずつ処理します。 |
サンプルコード
インデックス配列を定義して要素を参照する基本例です。メンバーリストを配列に格納します。
members=("user1" "user2" "user3" "user4")
echo ${members[0]}
echo ${members[2]}
echo ${#members[@]}
user1
user3
4
全要素をループで取り出すには ${arr[@]} をダブルクォートで囲んで使います。
team_members.sh
#!/bin/bash
members=("user1" "user2" "user3" "user4" "user5")
for member in "${members[@]}"; do
echo "Member: $member"
done
実行するコマンドは次の通りです。
bash team_members.sh Member: user1 Member: user2 Member: user3 Member: user4 Member: user5
declare -A で連想配列を宣言し、キーと値を格納する例です。ユーザー名と所属を対応づけます。
user_affiliation.sh
#!/bin/bash
declare -A affiliation
affiliation["user1"]="Team A"
affiliation["user5"]="Team B"
affiliation["user2"]="Team A"
for key in "${!affiliation[@]}"; do
echo "$key => ${affiliation[$key]}"
done
実行するコマンドは次の通りです。
bash user_affiliation.sh user2 => Team A user5 => Team B user1 => Team A
要素の追加・削除の例です。+= で末尾に追加し、unset で要素を削除します。
techniques=("method_a" "method_b" "method_c")
techniques+=("method_d")
echo ${techniques[@]}
unset techniques[1]
echo ${techniques[@]}
echo ${#techniques[@]}
method_a method_b method_c method_d
method_a method_c method_d
3
スライスを使うと配列の一部を切り出せます。${arr[@]:start:length} でインデックス start から length 個の要素を取得します。
items=("item_a" "item_b" "item_c" "item_d" "item_e")
echo ${items[@]:1:3}
item_b item_c item_d
task_log.sh
#!/bin/bash
# タスクログ処理スクリプト
declare -A email
email["user1"]="user1@example.com"
email["user2"]="user2@example.com"
email["user3"]="user3@example.com"
email["user4"]="user4@example.com"
email["user5"]="user5@example.com"
tasks=("Setup Environment" "Code Review" "Deploy Application" "Monitor System")
echo "=== Task List ==="
for i in "${!tasks[@]}"; do
echo "[$i] ${tasks[$i]}"
done
echo ""
echo "=== Member Contacts ==="
for name in "${!email[@]}"; do
echo "$name: ${email[$name]}"
done
echo ""
echo "Recent tasks: ${tasks[@]:1:2}"
概要
${arr[@]} と ${arr[*]} はどちらも全要素を展開しますが、ダブルクォートで囲んだ場合の挙動が異なります。"${arr[@]}" は各要素を個別の引数として渡すため、空白を含む要素が分割されません。"${arr[*]}" は全要素を IFS(デフォルト: スペース)で結合した1つの文字列として渡します。ループや関数呼び出しでは原則として "${arr[@]}" を使います。
unset で要素を削除しても、インデックスは詰められません。インデックス 1 を削除した場合、0, 2, 3, ... という飛び番号の配列になります。要素数 ${#arr[@]} は実際の要素数を返しますが、最大インデックスとは一致しない場合があります。インデックスを詰め直したいときは arr=("${arr[@]}") で再代入します。
Bash の配列は1次元のみです。多次元配列は直接サポートしていません。2次元データを扱う場合は、matrix_1_2 のような命名規則で複数の変数を使うか、文字列として格納して処理する方法がよく使われます。
よくあるミス
よくあるミス1: クォートなしで空白を含む要素が分割される
配列の展開時にダブルクォートを省略すると、空白を含む要素がシェルによって複数の引数に分割されます。
items=("value one" "value two" "value three")
for t in ${items[@]}; do
echo "$t"
done
value
one
value
two
value
three
クォートなしの ${items[@]} は、空白で分割されて6つの要素として処理されます。ダブルクォートで囲めば正しく3要素として扱われます。
for t in "${items[@]}"; do
echo "$t"
done
value one
value two
value three
よくあるミス2: 連想配列で declare -A を忘れる
declare -A を宣言せずに連想配列のように使うと、Bash はインデックス配列として扱います。文字列キーは数値に変換されて全て 0 として扱われるため、最後に代入した値だけが残ります。
affiliation["user1"]="Team A"
affiliation["user5"]="Team B"
affiliation["user2"]="Team A"
echo ${affiliation[@]}
Team A
3件代入したはずが1件しか残っていません。declare -A を先頭に追加すれば正しく動作します。
declare -A affiliation
affiliation["user1"]="Team A"
affiliation["user5"]="Team B"
affiliation["user2"]="Team A"
echo ${#affiliation[@]}
3
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。