gre*_*Dot 5 bash indirection unset
编辑:这已被确认是一个错误并将被修复:https : //lists.gnu.org/archive/html/bug-bash/2018-03/msg00055.html
所以我在搞砸 bash 的间接功能,namerefs。我以为我已经掌握了它的窍门,但是当我试图弄清楚如何将 namerefs 转换为常规变量时,我遇到了一些让我困惑的事情。
这是来自man bash:的相关段落:
declare -n为每个名称指定 nameref 属性,使其成为对另一个变量的名称引用。另一个变量由 name 的值定义。除了使用或更改 -n 属性本身的那些引用、赋值和属性修改之外,所有对 name 的引用、赋值和属性修改都是在 name 值引用的变量上执行的。
因此,假设您想取消设置 nameref——不是它指向的变量,而是变量本身。您不能只说unset foo,因为这实际上会取消设置foo指向的任何内容;相反,您必须将其设为常规变量,然后取消设置:
$ declare -p
$ foo=bar; bar='hello world'
$ declare -p
declare -- foo="bar"
declare -- bar="hello world"
$ declare -n foo; declare -p # 'foo' is now a nameref
declare -n foo="bar"
declare -- bar="hello world"
$ declare +n foo; declare -p # 'foo' is no longer a nameref
declare -- foo="bar"
declare -- bar="hello world"
$ unset foo; declare -p # 'foo' is unset, not bar
declare -- bar="hello world"
Run Code Online (Sandbox Code Playgroud)
这一切对我来说都有意义,并且与我对上述手册段落的阅读一致。让我感到困惑的是上面的一个小变化会发生什么——也就是说,我们bar没有设置和未声明:
...
$ declare -p
declare -n foo="bar"
$ echo "${foo}" # These two commands behave as expected--i.e., identically to how namerefs usually behave, just with an unset variable.
-bash: foo: unbound variable
$ echo "${!foo}"
bar
$ declare +n foo; declare -p # Should make 'foo' a regular variable, right? Nope.
declare -n foo="bar" # Still a nameref--wtf?
declare -- bar # And now bar's back--unset still, but declared. Wtf??
$ declare +n foo; declare -p # THIS, however, works like I thought it would--but *why*? In both cases 'bar' is unset...
declare -- foo="bar"
declare -- bar
Run Code Online (Sandbox Code Playgroud)
我显然误解了 namerefs 应该如何工作。根据 man 的文章,我认为取消设置foo应该对的 nameref 属性起作用foo,无论其目标是否bar未声明。
请注意,当bar未设置但已声明时,它会按照我的想法工作。这对我来说是最奇怪的部分——我没有意识到未声明变量有任何意义!test -v, ${var-_}, ${var+_}, 和set -u所有似乎只关心变量是否已设置,并且在 (A) 未设置的未声明变量和 (B) 未设置的已声明变量之间没有任何区别。
有人可以解释这里发生了什么,也许可以指出解释这一点的手册部分?namerefs 的行为是否还有其他特殊情况我会感到困惑?谢谢!
$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-unknown-linux-gnu)
...
$ echo "$-"
himuBCHs
Run Code Online (Sandbox Code Playgroud)
请注意,该行为在没有set -u; 的情况下仍然存在。我这样做只是为了让 bash 的消息更清晰一点。
| 归档时间: |
|
| 查看次数: |
2018 次 |
| 最近记录: |