bashの関数の引数に配列を渡す
bashの関数の引数に配列を渡したい時があります。様々な考え方があると思いますが、ここでは名前参照を利用して実現します。なお、筆者の名前参照に対する理解が浅いので、ここに書かれた表現が正確なのかは分かりません。なお、名前参照は、bash 4.3から実装された機能です。
環境:bash 5.1.16
スクリプト例
まずは、実際にコードを見てみましょう。スクリプトの引数にパスを指定すると、テキストと共にそのディレクトリの中身が表示されます。15行目のfn_show_list
関数の引数に配列dir_list
が渡されているのが分かります。
$ vi dirlist.sh
#!/bin/bash
declare -r dir_name=$1
declare -a dir_list=($(ls ${dir_name}))
fn_show_list() {
local -n arg=$1
for array in ${arg[@]}; do
echo "Exist the ${array} in ${dir_name}"
done
}
fn_main() {
fn_show_list dir_list | column -t
}
fn_main
実行すると次のように表示されます。
$ bash dirlist.sh ~/
Exist Desktop in /home/{USER}
Exist Documents in /home/{USER}
Exist Downloads in /home/{USER}
Exist GoogleDrive in /home/{USER}
Exist Scripts in /home/{USER}
詳細解説
では、コードを見ていきましょう。まず、変数と配列の宣言です。宣言は、ビルトインコマンドのdeclare
にオプションを付けます。オプションはそれぞれ、-r
がread(読み取り専用)、-a
がarray(配列)の意味です。
declare -r dir_name=$1
declare -a dir_list=($(ls ${dir_name}))
変数dir_name
に、引数が格納された位置パラメータ(第1引数なら$1
、第2引数なら$2
)を代入します。そして、配列dir_list
に、ls ${dir_name}
の結果を代入します。
つぎは、fn_show_list()
ではなく、先にfn_main()
をみましょう。
fn_main() {
fn_show_list dir_list | column -t
}
fn_main
fn_main()
の中で関数fn_show_list
を呼び出しています。また、関数fn_show_list
の引数に、配列名dir_list
が渡されています。
通常シェルスクリプトで関数の引数に配列を渡すことはできません。じゃあ、ここで渡しているのは何かというと、配列ではなく「配列名」ということになるのでしょうか(自信ありません)。しかし、関数の引数に配列名を渡しただけでは、使うことができません。最後にfn_show_list()
をみてみよう。
fn_show_list() {
local -n arg=$1
for array in ${arg[@]}; do
echo "Exist ${array} in ${dir_name}"
done
}
fn_show_list()
で特筆すべきことは、local -n arg=$1
の-n
の部分ですので詳しく見ていきます。
まず、ローカル変数を宣言する、local
コマンドにオプション-n
を付けてarg
宣言し、$1
を代入します。この位置パラメーター$1
は実行スクリプトの引数ではなく、fn_main()
で呼び出されたfn_show_list
の引数です。つまり、dir_list
という配列名が$1
に格納されており、その配列名がarg
というローカル変数に代入されました。
さて、いよいよ本題です。local
に付けられたオプションの-n
はname reference
(名前参照)と呼ばれるものです。名前参照は、変数や配列に入っている値を変数名として、間接的に値を参照できます。つまり、変数arg
は、配列dir_list
を参照します。
あとは変数arg
をfor
文で回せば前述の結果が表示されます。ぜひご自身で実験して見てください。