为什么这没有给出任何输出(除了换行符)而不是“ foo”?该代码使用在bash 4.3中引入的 nameref ,并且是“对另一个变量的引用”,它“允许间接操作变量”。
如果为库编写代码,应该采取什么措施来防止这种情况发生?
#!/usr/bin/bash
setret() {
local -n ret_ref=$1
local ret="foo"
ret_ref=$ret
}
setret ret
echo $ret
通过bash -x
运行它使我旋转,因为看起来它应该输出我期望的foo
:
+ setret ret
+ local -n ret_ref=ret
+ local ret=foo
+ ret_ref=foo
+ echo
有趣的是,它打印的是bar
,而不是foo
。
#!/usr/bin/bash
setret() {
local -n ret_ref=$1
ret_ref="bar"
local ret="foo"
ret_ref=$ret
}
setret ret
echo $ret
同样令人困惑的bash -x
输出:
+ setret ret
+ local -n ret_ref=ret
+ ret_ref=bar
+ local ret=foo
+ ret_ref=foo
+ echo bar
bar
答案 0 :(得分:1)
我希望这对其他人很有价值,因为在#bash
IRC频道中询问期望的输出得到了它的常规foo
之一的响应,这就是我的期望。 / p>
然后,他们让我挺直。 namerefs 不能像我想的那样工作。 local -n
未将ret_ref
设置为引用$1
。而是基本上将字符串ret
存储在ret_ref
中,标记为在使用时用作参考。
因此,尽管在我看来ret_ref
会引用调用者的ret
变量,但它只会这样做,直到函数定义了自己的本地ret
变量,然后它将引用代替那个。
如果为库编写代码,防止这种情况的唯一有保证的方法是在使用 namerefs 的任何函数中,使用以下所有函数名称为所有非nameref变量添加前缀:
#!/usr/bin/bash
setret() {
local -n ___setret_ret_ref=$1
local ___setret_ret="foo"
___setret_ret_ref=$___setret_ret
}
setret ret
echo $ret
非常丑陋,但必须避免碰撞。 (当然,可能有一些可行的方法,但是不太确定)。