【保存版】Bash配列チュートリアル:実例15選で基礎から応用まで完全マスター
配列とは、同じ型でも異なる型でも構わない複数の値を格納できる変数のことです。Bashの配列にはサイズの上限がなく、メンバー変数を連続したインデックスで代入・管理する必要もありません。なお、配列のインデックスは0から始まります。
この記事では、Bashにおける15種類の配列操作を順番に解説していきます。
本記事は連載「Bashチュートリアルシリーズ」の一部です。Bashスクリプトが初めての方は、まず「Bashスクリプト入門」のチュートリアルから読み進めることをおすすめします。
1. 配列の宣言と値の代入
Bashでは、次のような形式で変数を使用すると、配列が自動的に作成されます。
name[index]=value
- nameは配列につける任意の名前です
- indexには、0以上の数値として評価される任意の数字または式を指定できます。明示的に配列を宣言したい場合は declare -a arrayname を使用します。
$ cat arraymanip.sh
#! /bin/bash
Unix[0]='Debian'
Unix[1]='Red hat'
Unix[2]='Ubuntu'
Unix[3]='Suse'
echo ${Unix[1]}
$./arraymanip.sh
Red hat
配列の要素にアクセスするには、${name[index]} のように波括弧(ブレース)で囲みます。
2. 宣言時に配列を初期化する
各要素を個別に初期化する代わりに、波括弧の中に空白区切りの要素リストを指定することで、宣言と初期化を同時に行えます。
書式: declare -a arrayname=(element1 element2 element3)
要素に空白文字が含まれる場合は、引用符で囲んでください。
#! /bin/bash
$cat arraymanip.sh
declare -a Unix=('Debian' 'Red hat' 'Red hat' 'Suse' 'Fedora');
declare -a で配列を宣言し、括弧内のすべての要素がその配列の要素となります。
3. Bash配列全体を表示する
配列の全要素を表示する方法はいくつかあります。インデックス番号として @ または * を指定すると、配列のすべてのメンバーが参照されます。また、Bashのループ文を使って配列要素を順番にたどりながら表示することも可能です。
echo ${Unix[@]}
# 上記のecho文をarraymanip.shに追加して実行
#./t.sh
Debian Red hat Ubuntu Suse
インデックス番号を指定せずに配列のメンバー変数の内容を参照した場合、インデックス0で参照される最初の要素の内容を参照したことと同じになります。
4. Bash配列の長さ(要素数)を取得する
$# という特殊パラメータを使うことで、配列の長さを取得できます。
${#arrayname[@]} と書くと、配列の長さ(要素数)が得られます。
$ cat arraymanip.sh
declare -a Unix=('Debian' 'Red hat' 'Suse' 'Fedora');
echo ${#Unix[@]} #配列の要素数
echo ${#Unix} #配列の最初の要素の文字数(つまりDebianの文字数)
$./arraymanip.sh
4
6
5. 配列内のn番目の要素の長さを取得する
${#arrayname[n]} と書くと、配列内のn番目の要素の長さが得られます。
$cat arraymanip.sh
#! /bin/bash
Unix[0]='Debian'
Unix[1]='Red hat'
Unix[2]='Ubuntu'
Unix[3]='Suse'
echo ${#Unix[3]} # インデックス3にある要素(Suse)の長さ
$./arraymanip.sh
4
6. オフセットと長さによる配列からの抽出
次の例は、Unixという配列の3番目の位置から2つの要素を抽出する方法を示しています。
$cat arraymanip.sh
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
echo ${Unix[@]:3:2}
$./arraymanip.sh
Suse Fedora
上記の例では、インデックス3と4の要素が返されます。インデックスは常に0から始まる点に注意してください。
7. 特定の要素に対するオフセットと長さによる抽出
配列の特定の要素から一部だけを取り出すこともできます。例えば、配列のインデックス2に位置するUbuntuという要素から最初の4文字だけを抽出したい場合、オフセットと長さを指定します。
$cat arraymanip.sh
#! /bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
echo ${Unix[2]:0:4}
./arraymanip.sh
Ubun
上記の例では、配列のインデックス2の要素から先頭4文字が抽出されています。
8. 配列要素の検索と置換
次の例では、配列要素の中からUbuntuを検索し、それを「SCO Unix」という文字列に置き換えています。
$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
echo ${Unix[@]/Ubuntu/SCO Unix}
$./arraymanip.sh
Debian Red hat SCO Unix Suse Fedora UTS OpenLinux
この例では、インデックス2の要素「Ubuntu」が「SCO Unix」に置き換えられます。ただし、この方法では元の配列の内容は永続的には置き換えられない点に注意してください。
9. 既存のBash配列に要素を追加する
次の例は、既存の配列に新しい要素を追加する方法を示しています。
$cat arraymanip.sh
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Unix=("${Unix[@]}" "AIX" "HP-UX")
echo ${Unix[7]}
$./arraymanip.sh
AIX
Unixという配列に対して、「AIX」と「HP-UX」の要素がそれぞれインデックス7と8に追加されました。
10. 配列から要素を削除する
unset を使うと、配列から要素を削除できます。unsetは要素にnullを代入するのと同じ効果があります。
$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
unset Unix[3]
echo ${Unix[3]}
上記のスクリプトは、インデックス3に入っている値であるnullを出力するだけです。次の例は、配列から要素を完全に取り除く方法の一つを示しています。
$ cat arraymanip.sh
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
pos=3
Unix=(${Unix[@]:0:$pos} ${Unix[@]:$(($pos + 1))})
echo ${Unix[@]}
$./arraymanip.sh
Debian Red hat Ubuntu Fedora UTS OpenLinux
この例では、${Unix[@]:0:$pos} がインデックス0から始まる3つの要素(0、1、2)を返し、${Unix[@]:4} がインデックス4から最後までの要素を返します。そして両方の出力を結合しています。これは配列から要素を削除するための回避策の一つです。
11. パターンを使ってBash配列の要素を削除する
検索条件にパターンを指定し、残りの要素を別の配列に格納することができます。
$ cat arraymanip.sh
#!/bin/bash
declare -a Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora');
declare -a patter=( ${Unix[@]/Red*/} )
echo ${patter[@]}
$ ./arraymanip.sh
Debian Ubuntu Suse Fedora
上記の例では、パターン Red* に一致する要素が削除されています。
12. 配列をコピーする
配列の要素を展開し、それを新しい配列に格納します。
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Linux=("${Unix[@]}")
echo ${Linux[@]}
$ ./arraymanip.sh
Debian Red hat Ubuntu Fedora UTS OpenLinux
13. 2つのBash配列を連結する
2つの配列の要素を展開し、それを新しい配列に代入します。
$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Shell=('bash' 'csh' 'jsh' 'rsh' 'ksh' 'rc' 'tcsh');
UnixShell=("${Unix[@]}" "${Shell[@]}")
echo ${UnixShell[@]}
echo ${#UnixShell[@]}
$ ./arraymanip.sh
Debian Red hat Ubuntu Suse Fedora UTS OpenLinux bash csh jsh rsh ksh rc tcsh
14
これにより、「Unix」と「Shell」両方の配列の要素を持つ配列が出力され、新しい配列の要素数は14になります。
14. 配列全体を削除する
unset を使うと、配列全体を削除できます。
$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Shell=('bash' 'csh' 'jsh' 'rsh' 'ksh' 'rc' 'tcsh');
UnixShell=("${Unix[@]}" "${Shell[@]}")
unset UnixShell
echo ${#UnixShell[@]}
$ ./arraymanip.sh
0
配列をunsetすると、上記のようにその配列の長さはゼロになります。
15. ファイルの内容を配列に読み込む
ファイルの内容を行ごとに配列へ読み込むことができます。
#サンプルファイル
$ cat logfile
Welcome
to
thegeekstuff
Linux
Unix
$ cat loadcontent.sh
#!/bin/bash
filecontent=( `cat "logfile" ` )
for t in "${filecontent[@]}"
do
echo $t
done
echo "Read file content!"
$ ./loadcontent.sh
Welcome
to
thegeekstuff
Linux
Unix
Read file content!
上記の例では、forループを使って配列の各インデックスの要素が出力されています。
おすすめの書籍
Ramesh Natarajan著『Bash 101 Hacks』。筆者はほとんどの時間をLinux環境で過ごしているため、自然とBashのコマンドラインやシェルスクリプトの大ファンになりました。15年前、さまざまな*nix系OSで作業していた頃は、CシェルやKornシェルで多くのコードを書いていました。その後、システム管理者としてLinuxを使い始めてからは、Bashシェルスクリプトであらゆるタスクを自動化するようになりました。そうしたBashの経験をもとに、コマンドラインとシェルスクリプト両方の実用的な101の例を収録した電子書籍『Bash 101 Hacks』を執筆しました。Bashを本気でマスターしたいと考えているなら、ぜひこの本を読んで、Bashのコマンドラインとシェルスクリプトを思い通りに操れるようになりましょう。
-
Bashシェル関数入門:実用的な6つのサンプル例で学ぶチュートリアル
Bashシェル関数とは、複数のUNIX/Linuxコマンドをひとつの名前でグループ化し、後からまとめて実行できるようにする仕組みです。Bashシェル関数は通常のUnixコマンドと同じように呼び出すことができ、現在のシェルコンテキスト内で実行されるため、解釈用の新しいプロセスを生成する必要がありません。bashのエイリアス(alias)と関数はどちらも、長いコマンドや複雑なコマンドに対するショートカットを定義するのに役立ちます。しかし、エイリアスでは制御フローや引数の扱いなど、関数ならではの高度な処理を行うことはできません。本記事では、その違いも含めて詳しく解説していきます。この記事は、進行中の
-
実用的な5つの例で学ぶBashスクリプト入門チュートリアル
Unix SedやUnix Awkシリーズと同様に、本シリーズではBashスクリプティングに関する記事を複数回にわたって公開します。実用的なサンプルを交えながら、Bashスクリプティングのテクニックを幅広く解説していきます。 シェルとは、ユーザーが入力したコマンドを解釈して実行するプログラムです。コマンドはユーザーが直接入力するか、「シェルスクリプト」と呼ばれるファイルから読み込まれます。 ユーザーからの入力を直接読み取る場合、そのシェルは対話型(インタラクティブ)シェルと呼ばれます。 一方、ファイルからコマンドを読み込んで実行する場合は非対話型(ノンインタラクティブ)シェルと呼ばれます。この