zsh:変数を参照として渡し、その値を変更します(例:bashのlocal -n namerefs)。

zsh:変数を参照として渡し、その値を変更します(例:bashのlocal -n namerefs)。

evalを使用せずに変数をzsh関数に渡し、その値を変更できますか?私はこれを行うbashメソッドを見つけましたlocal -n。 ::https://stackoverflow.com/a/50281697

答え1

typeset -n実際、もともとksh93(1993)から出てきました。 2014年にリリースされたbash 4.3にも同様の内容が追加されました。 ksh93では、bash / zshの動的スコープ(関数が常に呼び出し元のローカル変数1を表示している場合)とは異なり、ksh93は静的スコープ(エクスポートしないと呼び出し元はローカル変数にアクセスできません)を実行するため、これは便利です。また見なさい:

$ bash -c 'function f { typeset -n var=$1; var=x;}; var=0; f var; echo "$var"'
environment: line 0: typeset: warning: var: circular name reference
environment: warning: var: circular name reference
environment: warning: var: circular name reference
x
$ ksh -c 'function f { typeset -n var=$1; var=x;}; var=0; f var; echo "$var"'
x

zshには拡張と割り当てのための変数逆参照演算子がありますが、namerefをサポートしていません。

$ expand() print -r -- ${(P)1}
$ assign() : ${(P)1::=$2}
$ var=foo
$ expand var
foo
$ assign var bar
$ print -r -- $var
bar

evalまたは、いつでもBourneに似たシェルで動作する標準的な方法を使用できます。

expand() {
  eval 'printf "%s\n" "${'"$1"'}"'
}
assign() {
  eval "$1=\$2"
}

尋ねる前にいいえP。ここでのように正しく行われると、bashでフラグや名前参照を使用するよりも安全ではありません。どの方法を使用しても、重要なこと名前変数の値が適切に制御されます。

assign var "$external_input"namerefを使用するか、使用しないかにかかわらずassign "$external_input" value安全です。またはwhichと同じで、bash/ksh/zshの任意のコマンド実行の脆弱性です。expand "$external_input"Peval[ -v "$external_input" ]read "$external_input"

また、見ることができますzsh-workersメーリングリストに関するディスカッションさまざまな間接配分方法の利点について説明します。

それから2001年の議論ksh93スタイルのnamerefサポートをzshに追加することを検討しています。そして2015年に再びそして2023年、これはその機能を追加することに興味があり、5.10か6.0であれ、最終的に5.9以降の次のバージョンに追加できることを示します。


1関数専用にするには、zsh/param/privateモジュールの変数を参照してください。zsh

関連情報