配列
sh には汎用的な配列がない。(bash にはある。)
Bourne Shell で期待される通りの挙動をする唯一の配列は $@ である。 疑似的に配列を扱う方法
eval を使って変数名を組み立てて使う。
code:array.sh
# 配列への設定
# $1 配列名
# $2 添字
# $3 値
array_put() {
eval "$1_$2=\"$3\""
}
# 配列からの取得
# $1 配列名
# $2 添字
array_get() {
eval "printf \"%s\" \"\${$1_$2}\""
}
# 配列の要素数の取得
# $1 配列名
array_count() {
set | grep "^$1_0-9*=" | wc -l }
$@ を配列として保存したい場合
$@ を1つの変数に代入するとIFSを区切りとした文字列に変換されてしまうため、そのままでは代入できない。
空白入りの値を正しく残そうとすると、必ず別々の変数に代入する必要がある。
$@ は関数を呼ぶと関数の局所変数になってしまう事に注意が必要。
eval を使わないと変数名は組み立てられない。
$@ でなくても、不定長の引数を配列にセットすることができる。
code:array_save.sh
# Save $@ to array
# @param $1 array name
# @param $2...
#
# How to use
# array_save YOURVAR "$@"
array_save() {
array_save_VAR=$1
shift
array_save_i=1
for array_save_item in "$@"
do
eval "${array_save_VAR}_${array_save_i}=\"$array_save_item\""
array_save_i=$((array_save_i+1))
done
unset array_save_VAR array_save_i array_save_item
}
保存した配列を $@ に設定する場合
配列の添字は1から順に並んでいなければならない。
set -f でファイル名展開を抑制する。
-- で以後のオプション解析(先頭ハイフン付き引数の解釈)の抑制
ダブルクォーテーションで括られた変数名の連続文字列を作り出す。
$@ は関数を呼ぶと関数の局所変数になってしまうため、関数の外で set を行うしかない。
seq を使うと簡単に書けるので使っている。(seq は POSIX 準拠ではなく、GNU Coreutils)
(POSIX 原理主義的には自力で文字列組立の方が良いだろうか?)
code:set_to_at.sh
array_list() {
seq -s ' ' $(array_count $1) | sed -e 's/\(1-90-9*\)/"\$'$1'_\1"/g' }
eval "set -f -- "$(array_list MYVAR)
とりあえずまとめた
参考