Skip to content

Instantly share code, notes, and snippets.

@showa-yojyo
Created August 5, 2026 14:35
Show Gist options
  • Select an option

  • Save showa-yojyo/65d2f961a991f1808b70c7a095394a2a to your computer and use it in GitHub Desktop.

Select an option

Save showa-yojyo/65d2f961a991f1808b70c7a095394a2a to your computer and use it in GitHub Desktop.
WIP
author プレハブ小屋 <2386769+showa-yojyo@users.noreply.github.com>
created 2026-08-05
draft true
tags
bash
array
title Bash 配列ノート

Bash 配列ノート

基本的性質

Bash では一次元の配列が使える。基本的な性質を羅列しておく:

  • 添字型と連想型がある。
    • 添字型配列では、添字は数とする。添字の最小元は 0 とする。
    • 連想型配列は、キーとして任意の文字列を使える。
  • 命令 declare -a で配列型変数を明示的に宣言することが可能。
  • 配列の長さに仕様による制限はない。

添字型配列の添字部分に対しては、次の性質がある:

  • 各種展開、命令置換、引用符除去が発生する。
  • 添字の値が空文字列の場合、添字 0 とみなされる。

連想配列のキー部分に対しては、次の性質がある:

  • tilde 展開を含む各種展開、命令置換、引用符が発生する。
  • 空文字列はキーとして認められない。

基本的操作

配列を宣言・初期化・生成する

添字型配列を、初期値を指定せずに、その名前だけを宣言するには次の組み込み命令を使え:

  • declare -a name
  • local -a name
  • readonly -a name

連想配列の宣言については、上の -a の代わりに -A を使え。

配列変数に nameref 属性を指定する (i.e. -n) ことは不可。

Tip

関数内部では local が使いやすい。対話型セッションでは declare がいい。

初期値を指定する場合は次の記法がいい:

name=([sub0]=value0 [sub1]=value1 ... )
  • 上記の宣言コマンドを用いても用いなくてもいい。
  • 添字配列の場合には [sub]= 指定すべてを省くのが普通だ。
  • value には任意の文字列を使える。
  • value にはシェル展開が適用される。複数の語に展開される場合は、語のそれぞれが個別の値になる。

Note

連想配列には、キーと値を交互に並べた配列で代入する記法もある。本稿では取り扱わない。

read -a を用いる

標準入力から添字型配列を構築する手段として命令 read -a name が使える。例:

$ read -a browsers
chrome firefox opera  # stdin
$ echo ${browsers[@]}
chrome firefox opera

mapfile/readarray を用いる

組み込みコマンド mapfile or readarray を使うことで、標準入力の各行が要素になるように配列を作成することが可能だ。例:

$ readarray -t users </etc/passwd
$ echo ${users[0]}
root:x:0:0:root:/root:/bin/bash
$ echo ${users[1]}
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
  • 通例、オプション -t を指定して行末の改行文字を落とす。
  • オプション -u fd を指定すれば、標準入力つまりファイル記述子 0 以外から入力できる。

配列を破棄する

添字型でも連想型でも、配列変数を全体的に破棄するのに、組み込み命令 unset を用いることができる。

添字配列の例:

$ declare -a browsers=(chrome firefox)
$ unset browsers
$ declare -p browsers
-bash: declare: browsers: not found

連想配列の例:

$ declare -A shells=([sh]=1979 [ksh]=1983 [tcsh]=1981 [bash]=1989)
$ unset shells
$ declare -p shells
-bash: declare: shells: not found

代入

配列全体を代入する場合は結局先述の初期化方式しかないらしい?

要素の値を代入するには次の記法を使え:

name[sub]=value
  • sub を指定しなくてもよい。その場合は最後に割り当てられた添字に対応する位置の次に新しい要素を挿し込む。
  • 添字型:sub が負の値の場合、Python list のように、末端からの相対位置に値を代入する。

要素を参照する

添字型配列の sub 番目の要素や、連想配列のキー sub に対応する要素を参照するには次の記法を使え:

${name[sub]}
  • 添字型:負の添字については代入の節で述べたとおり機能する。
  • 添字型:$name${name[0]} と同値。

命令の実引数として配列要素を渡す場合、それを囲む引用符の有無が変数展開を決める。例えば

some-command "a[4]"

a[4] を変数展開各種を施してから some-command が走る。一方、

some-command 'a[4]'

では、変数展開をいっさい行わないで命令を走らせる。

配列が未定義か空かであるかを調べる

未定義か空かを区別する必要がない場合には test -v name が手ッとり早く書ける。

if [[ -v name ]]; then
    echo name is not empty
else
    echo name is empty or unset
fi

配列を空にする

添字型配列に限り、unset "name[@]" により長さゼロの配列に変更することが可能。

$ declare -a arr=(0 1 2 3)
$ unset 'arr[@]'
$ declare -p arr
declare -a arr=()

Note

上記のような操作を連想配列に対して行うと、単純にキーが @ の要素があればそのキーと値の対が削除される。

部分列を作る

変数から部分文字列を作るための次の構文を配列に適用することが可能だ:

${name[@]:offset}
${name[@]:offset:length}

次の例は Bash Reference Manual Edition 5.3 p. 32 より引用:

$ array=(0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h)
$ echo ${array[@]:7}
7 8 9 0 a b c d e f g h
$ echo ${array[@]:7:2}
7 8
$ echo ${array[@]: -7:2}
b c
$ echo ${array[@]: -7:-2}
-bash: -2: substring expression < 0
$ echo ${array[@]:0}
0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h
$ echo ${array[@]:0:2}
0 1
$ echo ${array[@]: -7:0}

配列に要素を追加する

演算子 += で配列に要素を追加することが可能だ。

連想配列の例:

$ declare -A shells=([sh]=1979 [ksh]=1983 [tcsh]=1981 [bash]=1989 [zsh]=1990 [dash]=1997 [fish]=2005)
$ shells+=([csh]=1978)
$ echo ${shells[*]}
1981 1979 1989 1978 1997 1990 1983 2005
$ declare -p shells

標準入力から追加する場合には組み込み命令 mapfilereadarray のオプション -O が有用だ。

readarray -t -O ${#name[@]} name < ...

配列の添字 or キー全体を得る

添字型配列または連想配列 name の添字全部またはキー全部を得るには次のように書け:

${!name[@]}
${!name[*]}

これらの違いは引用符で囲んだときに生じる:

$ declare -A name=([sh]=1977 [bash]=1989 [zsh]=1990)
$ printf "%s\n" "${!name[@]}"
sh
bash
zsh
$ printf "%s\n" "${!name[*]}"
sh bash zsh

配列の内容を再利用可能な形式で出力する

配列を再利用可能な形式、つまりコピー&ペーストでその配列を再現することが可能な文字列として出力するには、declare -p が使える。

declare -p name

添字型配列の例を示す。やや冗長だが正確な表現をする:

$ declare -a browsers=(explorer chrome firefox edge)
$ declare -p browsers
declare -a browsers=([0]="chrome" [1]="firefox" [2]="opera")

配列の要素を削除する

unset "name[sub]"
  • 配列変数の最後の要素を削除しても、配列変数自体は消滅しない。
  • 添字型:添字はシフトしないらしい。下の例を見ろ。
$ declare -a browsers=(explorer chrome firefox edge)
$ unset "browsers[explorer]"
$ declare -p browsers
declare -a browsers=([1]="chrome" [2]="firefox" [3]="edge")

配列の長さを得る

配列の長さを得るには、変数の文字列としての長さを得る構文を使い回せ:

${#name[@]}
${#name[*]}

配列要素をループで巡る

for i in "${name[@]}"; do
    echo $i
done

シェル変数展開を配列の要素すべてに適用する

シェル変数展開を配列の要素すべてに適用した配列は容易に得られる。

例として、要素すべての値を大文字に変換した配列を作るには、展開式 @U^^${name[@]} に適用すればいい

$ declare -a browsers=(explorer chrome firefox edge)
$ echo ${browsers[@]@U}  # or ${browsers[@]^^}
EXPLORER CHROME FIREFOX EDGE

array_expand_once

shopt -s array_expand_once である場合、Bash は次の頃合いで配列の添字・キーに対する二重評価を避けるようになる:

  • 算術式の評価中
  • 変数代入を行う組み込み命令の実行中
  • 配列を間接参照する組み込み命令の実行中

TODO: 例を見つける


以上

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment