zsh:通过引用传递变量,并修改其值(如 bash 的 local -n namerefs)?

zsh:通过引用传递变量,并修改其值(如 bash 的 local -n namerefs)?

是否可以将变量传递给 zsh 函数,并在不使用 eval 的情况下修改其值?我遇到了一种 bash 方法来做到这一点local -n::https://stackoverflow.com/a/50281697

答案1

typeset -n实际上最初来自 ksh93 (1993)。 bash 在 2014 年发布的 4.3 中添加了类似的内容。在 ksh93 中,它更有用,因为 ksh93 执行静态作用域(您无法从调用者访问局部变量,除非它们被导出),而不是 bash/zsh 中的动态作用域(其中函数总是看到其调用者的局部变量 1)。也可以看看:

$ 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 的 shell 中工作:

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

在你问之前,不,这并不比P在 bash 中使用 flag 或 namerefs 更不安全,只要它像这里一样正确完成。无论采用何种方法,重要的是姓名变量的值得到适当的控制。

assign var "$external_input"无论您使用、 namerefs 还是,assign "$external_input" value是否安全。与with或which相同,都是bash/ksh/zsh 中的任意命令执行漏洞。expand "$external_input"Peval[ -v "$external_input" ]read "$external_input"

也可以看看zsh-workers 邮件列表上的讨论关于进行间接分配的各种方法的优点。

然后2001年的讨论正在考虑向 zsh 添加 ksh93 风格的 nameref 支持。和2015年再次2023年,表明人们有兴趣添加该功能,并且最终可能会在 5.9 之后的下一个版本中添加该功能,无论是 5.10 还是 6.0。


1 尽管请参阅zsh/param/private模块中的zsh变量以使其成为函数的私有变量。

相关内容