bash和ksh中的间接引用

时间:2013-10-05 21:48:26

标签: bash scope pass-by-reference ksh

我在bash和ksh中都有间接问题。以下示例适用于ksh。它使用nameref(typeset -n),但它不能像我预期的那样工作。 func_a将数组的名称传递给func_b,以便可以对其进行修改(在这种简单的情况下,func_b会向数组添加第二个条目)。这显然不起作用,因为func_b中定义的第二个局部var发生了 与nameref var2引用的名称相同(来自func_a的数组var1)。 但是具有本机nameref类型的原因之一(与bash中使用的各种eval hack相反)不应该不必处理这些动态范围问题,其中函数(在这种情况下为func_b)工作适用于某些来电者 函数,而不仅仅因为本地定义的变量的名称? 似乎nameref var基本上只是一个别名或宏,而不是连接两个严格分隔的范围的安全方法。我和bash有同样的问题,我希望ksh能像C一样实现间接引用(当然,出于安全原因,不像低级指针,但至少有类似的“范围隔离”可以这么说)。我错过了什么吗?

func_b ()
{
  typeset -n var2=$1
  typeset -i var1

  var2[1]=b
}


func_a ()
{
 typeset -a var1=( a )
 func_b var1
 echo "${var1[@]}"
}

2 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,这家伙做了http://fvue.nl/wiki/Bash:_Passing_variables_by_reference 如此完全归功于他。我不喜欢他使用他关于bash未设置的发现的方式 但任何人都可以用自己的方式使用这个属性。所以这是它的要点:

上面的代码在bash中就是这样的

func_b ()
{
  local var2=$1
  local -i var1
#do some work to compute the value b
#....
#....
#And in the end assign it with the indirect reference
  eval "$var2[1]=b"
}


func_a ()
{
 local -a var1=( a )
 func_b var1
 echo "${var1[@]}"
}

(可以避免使用eval,但让我们坚持下去) 显然问题是func_b中的局部var1会影响func_a中的var1 由func_b中的var2引用。因此func_b确实按预期行事,即第二个条目 在调用者的数组中通过间接引用添加,仅在调用者没有时添加 将其数组命名为“var1”。让我们说在“做一些工作”之后,我知道我已经完成了 使用我在func_b中使用的局部变量var1(可能用于计算想要的值) 价值b)。此时我可以做到这一点

func_b ()
{
  local var2=$1
  local -i var1
#do some work to compute the value b
#....
#....
#And in the end assign it with the indirect reference
  unset var1 
  eval "$var2[1]=b"
}

删除func_a的var1上的“shadow”并正确终止计算。 但bash unset不允许这样做。一旦我在func_b中设置了loval var1,即使 在某些时候我取消了它,它仍然会影响func_a的var1。 上面发现的是,unset实际上可以通过调用堆栈到达 并取消设置func_b的var1,但仅在func_b调用之上的函数f调用时调用 在堆栈中IF函数f没有在本地定义它自己的var1。 基本上如果你这样做

func_the_unshadower ()
{
  unset -v var1
}

func_b ()
{
  local var2=$1
  local -i var1
#do some work to compute the value b
#....
#....
#And in the end assign it with the indirect reference
  func_the_unshadower
  eval "$var2[1]=b"
}

func_a ()
{
 local -a var1=( a )
 func_b var1
 echo "${var1[@]}"
}

它有效.... 显然这只是一个玩具的例子,每个人都可以找出他们的首选 使用unset这个属性的方法。一个简单的方法是在运行时检查引用的变量 通过调用“local”而不使用参数(通过名称)将某些本地var遮蔽 返回本地变量列表)。 但最棒的是,这不是bash中的错误。在上面的链接中 甚至链接到bash邮件列表中主要bash开发人员的线程 他说,这就是未设置的方式,并且会保持这种状态。

答案 1 :(得分:0)

我发现用语法声明函数:

function func_a

它有效。这是因为这个ksh93语法使得排版声明变量是局部的,而原始语法适用POSIX规则并且变量是全局的。

皮特