当我在函数中声明一个本地数组时,为什么bash会抛出未绑定的变量警告?

时间:2015-03-27 20:40:53

标签: bash msys

在这个示例中,声明具有与全局范围不同的名称的局部变量不会产生错误,但是当name与global得到的相同时:

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[@]

2 个答案:

答案 0 :(得分:3)

为了确保我们在同一张纸上,这是适用于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

答案 1 :(得分:0)

更新:似乎如何声明您函数中传递的数组会影响阴影名称是否有效,即使在新的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的答案{{3} }。

以上两种功能一直用于工作。

现在,在我的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}")的“本地”习语,我可以解决这个问题。

所以,这段代码

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

testArrayArg3 anArray[@]

工作的:

testArrayArg3: a b c

~~~~~~~~~~

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

我在上面here下隐藏评论中提到的SO链接中提到了这个习语。要查看它,请单击“显示3个以上”链接并查看Mike Q的评论。

它是否与declare -a anArray=("${!1}")成语一样好,或者它有自己的缺点?

我有一些关键代码依赖于将数组传递给bash函数,所以我真的需要直截了当。