作曲・浄書・指導・音響

金沢音楽制作

金沢音楽制作では、楽曲・楽譜の制作と、作曲や写譜などレッスンを行っています。

bashの関数の引数に配列を渡す

bashの関数の引数に配列を渡したい時がある。様々なやり方があるようだが、ここでは変数宣言で名前参照を利用する。これはbash 4.3から実装された機能なので、バージョンの確認が必要である。

スクリプト例

スクリプト例を下掲に示す。これは、スクリプトの引数にパスを指定すると、テキストと共にそのディレクトリの中身が表示されるものである。

$ vi dirlist.sh
#!/bin/bash

declare -r dir_name=$1
declare -a dir_list=($(ls ${dir_name}))

show_list() {
  local -n arg=$1

  for array in ${arg[@]}; do
    echo "Exist the ${array} in ${dir_name}"
  done
}

main_func() {
  show_list dir_list | column -t
}

main_func

実行すると次のように表示される。

$ bash dirlist.sh ~/
Exist  Desktop      in  /home/hase
Exist  Documents    in  /home/hase
Exist  Downloads    in  /home/hase
Exist  GoogleDrive  in  /home/hase
Exist  Scripts      in  /home/hase

[目次へ]

詳細解説

コードを見ていく。まず、変数と配列の宣言である。宣言にはdeclare(組み込みコマンド)を使用する。オプションはそれぞれ、-rがread(読み取り専用)、-aがarray(配列)である。

declare -r dir_name=$1
declare -a dir_list=($(ls ${dir_name}))

引数が格納された位置パラメータ(第1引数なら$1、第2引数なら$2)を、変数dir_nameに代入する。そして、引数で入力されたパスのlsの結果を配列dir_listに代入する。

つぎは、show_list()ではなく、先にmain_func()をみよう。(シェルスクリプトにおいて、main関数を用意している例は少ないが、保守の観点から見ると積極的に使うべきだと考えている。)

main_func() {
  show_list dir_list | column -t
}

main_func

main_func()の中で関数show_listを呼び出している。また、関数show_listの引数には、配列名dir_listが記述されている。通常、引数に配列を渡すことはできない。したがって、ここで渡しているのは配列ではなく、「配列名」である。なお、パイプ(|)でつないだcolumn -tは、整列させるコマンドである。

関数の引数に配列名を渡したが、そのままでは使うことができない。最後にshow_list()をみてみよう。

show_list() {
  local -n arg=$1

  for array in ${arg[@]}; do
    echo "Exist ${array} in ${dir_name}"
  done
}

show_list()で特筆すべきは、local -n arg=$1であるので詳しく見ていく。localは変数を宣言した関数の中でのみ機能させる(ローカル変数)コマンドである。そのローカル変数argに$1を代入する。この位置パラメーター$1は実行スクリプトの引数(前例では~/)ではなく、main_func()で呼び出されたshow_listの引数である。つまり、dir_listという配列名が$1に格納されており、その配列名がargというローカル変数に代入されたのである。

さて、localにつけられたオプションの-nはname reference(名前参照)と呼ばれるものであり、変数や配列に入っている値を変数名として、間接的に値を参照できる。つまり、変数argは、配列dir_listを参照するC言語のポインタのような働きをするのである(この表現が正しいか分からない)。あとは変数argをfor文で回せば前述の結果が表示される。

[目次へ]

[ノート一覧へ]

  • 公開日:2019-12-15