VARNAME
他の変数の名前を含む変数があります。私はそれを使用せずに他の変数に割り当てたいと思いますeval
。どうすればいいですか?
使いたくない理由eval
は次のとおりです。まず、変数を前に追加する関数を想定しますfoo
。
% prepend_foo() { foo=("$@" $foo) }
% foo=(1 2)
% print -l $foo
1
2
% prepend_foo x 'a b c' y
% print -l $foo
x
a b c
y
1
2
%
それでは、変数に添付されている一般的な関数を考えてみましょう。
% prepend() { var=$1; shift; eval "$var=($@ ${(P)var})" }
% foo=(1 2)
% print -l $foo
1
2
% prepend foo x 'a b c' y
% print -l $foo
x
a
b
c
y
1
2
%
ご覧のように、空白のある変数は複数の配列項目に分割されます。私が望むことを達成するために引用符を正しく組み合わせることはできません。
IRCでは誰かが使用を提案しましたが、${name::=word}
これは配列では機能しません。
21:23 < someone> > b=(bar baz); a=b; : ${(P)a::=(foo ${(P)a})}; typeset -p b
21:23 < machabot> someone: typeset b='(foo bar baz)'
21:23 < someone> dammit that's a string
答え1
配列に要素を追加するには、次のようにします。
a[1,0]=(more elements)
またはこれを行うこともできます:
a=(more elements "$a[@]")
以下を行います。
a=(more elements $a)
の空の要素は削除されます$a
。
これを行うための関数を作成することが目的ですが、eval
構文が正しいことを確認する必要があります。
prepend() {
eval "${1}[1,0]"='("${@[2,-1]}")'
}
("${@[2,-1]}")
文字通りに渡されるように.を一重引用符で囲む方法を確認してくださいeval
。
またはより長い方法ですが、動作しませんprepend var more elements
(変数名がある場合var
)。
prepend() {
local var=$1; shift
eval "$var"='("$@" "${'"$var"'[@]}")'
}
eval
評価するコードはprepend varname ...
次のとおりです。
varname=("$@" "${varname[@]")
"$@"
に渡す前に拡張したくありませんeval
。$var
そこまで拡張するだけです。
変数拡張フラグは、クリーンアップされていないデータと共に使用すると同様に危険ですP
。eval
var='x[$(uname>&2)0]'
echo "${(P)var}"
コマンドuname
が実行されます。
答え2
一度に1つの要素を移動解除するために要素を繰り返すことで、関数なしでprepend
関数を作成できます。eval
$ prepend () {
then> local i=$#*
then> while [[ $i > 1 ]]; do
then> typeset -g "${1}[1,0]=$*[$i]"
then> i=$((i - 1))
then> done
then> }
$ foo=(a 'b c' d)
$ prepend foo m 'n o p' q r
$ print -l $foo
m
n o p
q
r
a
b c
d
$
組版は-g
ローカルではなく配列要素の設定を許可する必要がありますが、これが参照された配列が呼び出し$1
関数に対してローカルであることはできないという意味ではありません。これは単に「この配列は関数呼び出しスタックを検索することによって見つけることができます」を意味します。