関数内でローカルに$ path配列を設定するのはあまり複雑ではありませんか?

関数内でローカルに$ path配列を設定するのはあまり複雑ではありませんか?

$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}ローカル変数にスペースで区切られた単一の文字列のすべての個別のパスが含まれていることです。122$path

ベストアンサー1

PATH配列の代わりにスカラー型を使用してくださいpath。どちらかを作成すると、どちらも効果的にローカライズされます。したがって、次のようになります。

foo() {
  local PATH=$PATH
  if ( some_condition ) path=( $PREFIX $path )

  # do stuff
}

(一部のパスコンポーネントが含まれている場合は機能しません:。)

残念ながら、ローカル配列パラメータはステートメントで初期化できないため、元の値で初期化できません。

おすすめ記事