在 zsh 中的函数定义处扩展变量

在 zsh 中的函数定义处扩展变量

当我在 zsh 中定义函数时,我在尝试评估/扩展变量时遇到了一些麻烦 - 这可能吗?例子:

variable=foo
mytest(){
  echo ${variable}  
}
mytest           //outputs foo
variable=bar
test           //outputs bar

我希望 test() 中的变量保留 foo 并且不再受 $variable 的影响。我一直在阅读手册并尝试评估和不同的引用,但似乎没有任何效果。

答案1

您需要在函数内部有一个变量,一旦设置,它就会保留其值。由于这只能通过全局变量来完成,因此您需要给它一个不同的名称,例如:

xtest(){
  typeset -g test_variable
  : ${test_variable:=$variable}
  echo $test_variable
}

这会test_variable在第一次调用该函数时设置,但之后不会覆盖它。

更新:根据 Stéphane Chazelas 给出的评论更改了函数定义的语法,并将我的函数从 test 重命名为 xtest,因为无论如何将函数命名为“test”都是一个坏主意。

答案2

zsh首先请注意, Bourne shell 中的函数定义语法为:

funcname() cmd

(尽管它也支持 ksh 语法function funcname {...}和其他一些语法)。

fun不是zsh语法关键字。对于fun foo() cmd,您可以将 afunfoo函数定义cmd为主体。

我还建议不要使用标准命令(内置命令和大多数其他类似 Bourne 的 shell)的test名称作为函数名称。testzsh

如果你想要一个带有当地的具有固定值的变量,您需要将该值嵌入到函数的定义中:

mytest() {
  local variable=test
  echo $variable
}

variable对于该函数来说是本地的,但对于该函数调用的其他函数(mytest如果有)仍然可见。如果您希望它对其他函数隐藏,即进行静态作用域,您可以使用private(在zsh/param/private模块中)而不是local.

如果你想要那个固定值$variable作为定义时全局变量的值mytest,您仍然需要将其嵌入到定义中,如下所示:

zmodload zsh/param/private
eval '
  mytest() {
    private variable='${(qq)variable}'
    echo $variable
    otherfunction ...
  }
'

${(qq)...}我们在定义中嵌入变量的内容(用 正确引用)。

相关内容