shやbashにはselectという便利な構文がある。select構文を使うとin以降に与えた複数の引数をメニューっぽく表示して選択させてくれる。数字を選択すると、対応する引数の値が指定された変数に代入されdo以下が実行される。範囲外の数字を入力すると再度入力を促される。Enterだけ入力すると再度メニューが表示される。Ctrl-Dを押下するとselect文は終了する。
/bin/shの場合
➤ env -i /bin/sh
sh-4.1$
sh-4.1$ select x in aa bb cc; do echo $x; done
1) aa
2) bb
3) cc
# ? 3
cc
inの後に複数の引数ではなくセミコロン、コロン、スペースなどで区切った文字列を渡しても気を利かせてくれるわけではない。
sh-4.1$ select x in "aa;bb"; do echo $x; done
1) aa;bb
# ?
sh-4.1$ select x in "aa:bb"; do echo $x; done
1) aa:bb
# ?
sh-4.1$ select x in "aa bb"; do echo $x; done
1) aa bb
# ?
/bin/bashの場合
shでは変数に型という概念は無く、すべての変数はただの文字列である。
これに対してbashの変数は値として配列もとることができる。
そこでselect構文においてinの後に配列を持つ変数を展開すべく
$mを書いてみたが、単に${m[0]}の代わりにしかならなかった。
$ env -i /bin/bash
bash-4.1$ m[0]=item1
bash-4.1$ m[1]=item2
bash-4.1$ m[2]=item3
$ declare -p m
declare -a m='([0]="item1" [1]="item2" [2]="item3")'
bash-4.1$ select x in $m; do echo $x; done
1) item1
# ? 1
item1
おまけ)bashにおける配列型変数
bashでは変数が配列を持っている場合 [0]や[1]というインデックス
を省略すると、それは単に[0]を指すだけである。
$ declare -p m
declare -a m='([0]="item1" [1]="item2" [2]="item3")'
$ echo $m
item1
$ echo ${m}
item1
$ echo ${m[0]}
item1
$ declare -p m
$ m=hogehoge
$ declare -p m
declare -a m='([0]="hogehoge" [1]="item2" [2]="item3")'
$ echo $m
hogehoge
おまけの続き)
コメントでbashで配列を持っている変数の添え字(?)に@を使うとすべての要素が取り出せるよと @akinomyoga さんに教えていただきました。
$ x[0]=aa
$ x[1]=bb
$ echo ${x[@]}
aa bb
$ select y in "${x[@]}"; do echo $y; done
1) aa
2) bb
# ? 1
aa