为什么 `man bash` 页面声明了 `declare` 和 `local` `-n` 属性 "cannot be applied to array variables",但它可以?

Why do the `man bash` pages state the `declare` and `local` `-n` attribute "cannot be applied to array variables", and yet it can?

为什么 local -n 对数组变量起作用,而手册 明确表示它不能 ?说明书错了吗?这是否依赖于某种 ​​bash “未定义的行为?”手册是否过时?我错过了什么吗?

这是我从 bash 手册中查看的信息:

运行 man bash 并使用正则表达式搜索模式 local \[ 搜索 local [。它说(强调):

local [option] [name[=value] ... | - ]

For each argument, a local variable named name is created, and assigned value. The option can be any of the options accepted by declare.

(另见 help local)。

因此,可以传递给 bash local 内置命令的选项与 declare 的选项相同。让我们找出哪些选项可以传递给 declare:

运行 man bash 并使用正则表达式搜索模式 declare \[ 搜索 declare [。在 -n 条目下 declare [-aAfFgilnrtux] [-p] [name[=value] ...] 你会看到(强调):

-n Give each name the nameref attribute, making it a name reference to another variable. That other variable is defined by the value of name. All references, assignments, and attribute modifications to name, except those using or changing the -n attribute itself, are performed on the variable referenced by name's value. The nameref attribute cannot be applied to array variables.

(另见 help declare)。

因此,尽管上面写着 “nameref 属性不能应用于数组变量”,,但 确实如此在数组变量上工作得很好!

为了证明这一点,这里有一个演示可以很好地用于 常规 bash 数组:

function foo {
    # declare a local **reference variable** (hence `-n`) named `data_ref`
    # which is a reference to the value stored in the first parameter
    # passed in
    local -n data_ref=""
    echo "${data_ref[0]}"
    echo "${data_ref[1]}"
}

# declare a regular bash "indexed" array
declare -a data
data+=("Fred Flintstone")
data+=("Barney Rubble")
foo "data"

示例输出:

Fred Flintstone
Barney Rubble

...它在关联bash数组(即:bash哈希表、“字典”或“无序地图"):

function foo {
    # declare a local **reference variable** (hence `-n`) named `data_ref`
    # which is a reference to the value stored in the first parameter
    # passed in
    local -n data_ref=""
    echo "${data_ref["a"]}"
    echo "${data_ref["b"]}"
}

# declare a bash associative array
declare -A data
data["a"]="Fred Flintstone"
data["b"]="Barney Rubble"
foo "data"

示例输出:

Fred Flintstone
Barney Rubble

我的 bash --version4.4.20(1)-release,在 Linux Ubuntu 18.04:

GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

参考文献:

  1. 我从@Todd Lehman 的回答中修改了上面的代码示例:How to pass an associative array as argument to a function in Bash?

注意:万一有人在搜索它,这个问题本身也回答了以下问题:“如何将 bash 数组作为参数传递给函数?”和“如何将 bash 关联数组作为参数传递给函数?”

您正在将 -n 应用于一个标量变量,然后让该 nameref 指向一个数组。这很好。

不能做的是将-n应用于数组变量以创建名称引用数组:

# Declare two variables
declare foo=42 bar=1337

# Make an array of namerefs
declare -n array=(foo bar)    # ERROR

# ${array[0]} is foo so this should print $foo, i.e. 42?
echo "${array[0]}"    

如果你尝试,Bash 会阻止你:

bash: declare: array: reference variable cannot be an array