$path
次のコードスニペットに示されているよりも、配列のローカルバージョンを設定するのが難しい方法はありますか?
foo () {
local holdpath
holdpath=($path)
local path
path=($holdpath)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
具体的にキャバレーショーを言うのにholdpath
…
私が定義すれば
foo () {
local path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
...最初の割り当てでエラーがpath
発生しました。bad pattern
もちろん、私が定義するなら
foo () {
local path
path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
...最初の割り当てにはpath
違いはありません(つまり、結果を変更せずに省略できます)。割り当てがあるかどうか$path
は空です。
編集する:
次のスクリプトは、これまでに受け取ったさまざまな提案をテストします。
foo_0 () {
echo ${#path}
local PATH=$PATH
echo ${#path}
}
foo_1 () {
echo ${#path}
eval "local path; path=(${(q)path})"
echo ${#path}
}
foo_2 () {
echo ${#path}
eval "$(local -p path)"
echo ${#path}
}
for i ( 0 1 2 ) {
fn=foo_$i
echo "# $fn"
$fn
echo
}
出力は次のとおりです
# foo_0
22
22
# foo_1
22
1
# foo_2
22
22
foo_0
したがって、との出力は、foo_2
少なくとも私が達成したいものと一致します。上記のように動作しないものがありますが、割り当て中にfoo_1
削除しました。(q)
path
foo_1 () {
echo ${#path}
eval "local path; path=($path)"
echo ${#path}
}
foo_0
...その後、出力はとの出力と一致しますfoo_2
。残念ながら、修飾子のドキュメントを何度も読んでも、元のq
レシピでどのような役割を果たしているのかよく理解できません。
また、次のコマンドラインバリアントが上記foo_0
のバリエーションと異なる理由を理解できません。
% (foo_0a () { echo ${#path}; local PATH=$PATH; echo ${#path} }; foo_0a)
22
1
そのコマンドラインバリアントであるFWIWは、foo_1
スクリプトfoo_2
のソースと同じ結果を生成します。
% (foo_1a () { echo ${#path}; eval "local path; path=(${(q)path})"; echo ${#path} }; foo_1a)
22
1
% (foo_2a () { echo ${#path}; eval "$(local -p path)"; echo ${#path}; }; foo_2a)
22
22
また、上記のすべてのケースで原因ではなく、結果は、echo ${#path}
ローカル変数にスペースで区切られた単一の文字列のすべての個別のパスが含まれていることです。1
22
$path
答え1
PATH
配列の代わりにスカラー型を使用してくださいpath
。どちらかを作成すると、どちらも効果的にローカライズされます。したがって、次のようになります。
foo() {
local PATH=$PATH
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
(一部のパスコンポーネントが含まれている場合は機能しません:
。)
残念ながら、ローカル配列パラメータはステートメントで初期化できないため、元の値で初期化できません。
答え2
そしてバンドル配列を使用できますリッチの答え、通常は次のようにすることができます。
foo() {
eval "local array; array=(${(q)array[@]})"
...
}
これは(q)
配列要素への参照です。たとえば、と同じ値の場合に$PATH
展開されます。文字列がに渡されるので、これらのスペースとドル文字をエスケープする必要があります。/foo bar:/x$y
"${(q)path[@]}"
/foo\ bar /x\$y
eval
次のようにすることもできます。
foo() {
eval "$(local -p array)"
...
}
すべての型の変数で動作しますが、これにより追加のプロセスが生成されます。