为什么 bash 当我在函数中声明一个名称覆盖全局数组的局部数组时抛出未绑定变量警告?

why bash throws unbound variable warning when I declare a local array in function whose name is shadowing a global one?

在此示例中,使用与全局范围的名称不同的名称声明局部变量不会产生错误,但是当名称与全局名称相同时,我得到:

line 5: !1: unbound variable

代码:

set -u
function get_arr {
  local myArr2=("${!1}")
  echo ${myArr2[*]}
  local myArr=("${!1}")
  echo ${myArr[*]}
}

myArr=(one two three)
get_arr myArr[@]

只是为了确保我们使用的是同一份 sheet 论文,这里是 Bash 3.2 上的版本(引用或未引用的都很好 ).您的文件中必须有环境设置或杂散字符,这些字符与您的脚本无关导致问题:

#!/bin/bash

set -u
function get_arr {
    local myArr2=("${!1}")
    echo ${myArr2[*]}
    local myArr=("${!1}")
    echo ${myArr[*]}
}

myArr=(one two three)
get_arr "myArr[@]"

exit 0

版本

$ bash --version
GNU bash, version 3.2.39(1)-release (i586-suse-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.

输出

$ bash array_indirect_ref.sh
one two three
one two three

执行

$ bash -x array_indirect_ref.sh
+ set -u
+ myArr=(one two three)
+ get_arr 'myArr[@]'
+ myArr2=("${!1}")
+ local myArr2
+ echo one two three
one two three
+ myArr=("${!1}")
+ local myArr
+ echo one two three
one two three

更新:看来你如何声明函数中传递的数组会影响隐藏名称是否有效,即使在新的bash 版本.

我有一些 bash 代码过去可以工作,截至上周,但在我将 cygwin 更新为其当前代码后现在失败了。

~~~~~~~~~~

我的 cygwin bash 版本现在是 4.3.39:

$ bash --version
GNU bash, version 4.3.39(2)-release (i686-pc-cygwin)

which is the latest.

~~~~~~~~~~

考虑这个 bash 代码:

#!/bin/bash
set -e  # exit on first failed command
set -u  # exit if encounter never set variable

testArrayArg1() {
    declare -a argArray=("${!1}")
    echo "testArrayArg1: ${argArray[@]}"
}

testArrayArg2() {
    declare -a anArray=("${!1}")
    echo "testArrayArg2: ${anArray[@]}"
}

anArray=("a" "b" "c")

testArrayArg1 anArray[@]
testArrayArg2 anArray[@]

请注意,testArrayArg2 函数使用数组名称 (anArray),它会遮盖脚本中的后续变量名称。

另请注意,我将数组传递给函数的方式 (anArray[@]) 以及我在函数中声明数组的方式 (declare -a anArray=("${!1}")) 均取自 Ken Bertelson 的回答 here.

上面的两个函数过去一直有效。

现在,在我的 cygwin/bash 更新后,testArrayArg1 仍然有效,但使用阴影数组名称的 testArrayArg2 失败:

$ bash t.sh
testArrayArg1: a b c
t.sh: line 11: !1: unbound variable

有人知道 bash 最近发生了什么变化导致了这个吗?

~~~~~~~~~~

如果我将在函数内声明数组的方式从 declare -a anArray=("${!1}") 更改为 local anArray=("${!1}") 的 "local" 习语,我可以解决此问题。

所以,这段代码

testArrayArg3() {
    local anArray=("${!1}")
    echo "testArrayArg3: ${anArray[@]}"
}

testArrayArg3 anArray[@]

作品:

testArrayArg3: a b c

~~~~~~~~~~

好的,所以 local anArray=("${!1}") 函数数组 arg 声明习惯用法似乎有效。

我在上面Ken Bertelson's answer下的隐藏评论中提到的那个SO link中提到了这个成语。要查看它,请单击 "show 3 more" link 并查看 Mike Q 的评论。

它是否与 declare -a anArray=("${!1}") 习语一样好,还是有其自身的缺点?

我有一些关键代码依赖于将数组传递给 bash 函数,所以我真的需要弄清楚这一点。