配列代わりに何かと便利な位置パラメタを退避できると嬉しいときがあるような気がした。
(esc関数の定義はここを参照)
arr() {
local RET args= arg
for arg in "$@"; do
esc "$arg"
printf ' %s' "$RET"
done
}
alias backup_args='arr "$@"'
alias restore_args='eval "set --"'
$ set -- 'a b' "c'"
$ hoge="`backup_args`"
$ echo $hoge
'a b' 'c'\'''
$ set --
$ echo "$1"
$ restore_args "$hoge"
$ echo "$1"
a b
$ echo "$2"
c'
evalで解釈するとシングルクォート囲みの文字列が各フィールドにsetされるように
文字列を作成するだけなのだが、これを使うと任意の文字列の配列が入れ子で
作成できることに気がついた。
$ m=$(arr "`arr 1 2 3`" \
"`arr 4 5 6`" \
"`arr 7 8 9`")
$ echo $m
' '\''1'\'' '\''2'\'' '\''3'\''' ' '\''4'\'' '\''5'\'' '\''6'\''' ' '\''7'\'' '\''8'\'' '\''9'\'''
$ restore_args "$m"
$ echo $2
'4' '5' '6'
$ restore_args "$2"
$ echo $1
4
$ echo $2
5
位置パラメタを汚さずにアクセスできるようにiter関数を定義してみる。
iter() {
local head=$1 tail=$2
eval "restore_args \"\$$2\""
[ $# -gt 0 ] || return
eval "$head='$1'"
shift
eval "$tail="'"`backup_args`"'
}
$ a="`arr 1 2 3 4`"
$ while iter i a; do echo $i; done
1
2
3
4
※性能を気にする人はコマンド置換を避けて定義し直すとよいかも。