是否可以将变量传递给 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"
P
eval
[ -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
变量以使其成为函数的私有变量。