1

In this example declaring local variable with different name from that of global scope produces no error but when name is the same as global I get:

line 5: !1: unbound variable

code:

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

myArr=(one two three)
get_arr myArr[@]
rsk82
  • 28,217
  • 50
  • 150
  • 240

2 Answers2

4

Just to make sure we are on the same sheet of paper, here is the version working on Bash 3.2 (works fine quoted or unquoted). You must either have an environment setting or stray characters in your file, of something unrelated to your script causing issues:

#!/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

Version

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

Output

$ bash array_indirect_ref.sh
one two three
one two three

Execution

$ 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
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Ah yes, now I've downloaded msys bash 3.2.51 from here: http://lrn.no-ip.info/other/mingw/msys/bash/ - and indeed this works, so the whole issue was a bug in 3.1. Well I didn't know that there is 3.2 available, google or msys installer both gave me 3.1. – rsk82 Mar 27 '15 at 21:59
  • I didn't know it was available either -- I just happened to have an old fax server running openSuSE 11.0 at the office `:p` – David C. Rankin Mar 27 '15 at 22:06
0

Update: it appears that how you declare the passed array inside your function affects whether or not shadowed names will work, even in new bash versions.

I have some bash code that used to work, as of last week, but now fails after I updated cygwin to its current code.

~~~~~~~~~~

My cygwin bash version is now 4.3.39:

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

which is the latest.

~~~~~~~~~~

Consider this bash code:

#!/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[@]

Note that testArrayArg2 function uses an array name (anArray) which shadows the subsequent variable name in the script.

Also note that the way I pass the array to the function (anArray[@]) and the way that I declare the array in the function (declare -a anArray=("${!1}")) are taken from Ken Bertelson's answer here.

Both functions above used to always work.

Now, after my cygwin/bash update, testArrayArg1 still works but testArrayArg2 which uses a shadowed array name fails:

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

Anyone know what changed recently in bash to cause this?

~~~~~~~~~~

I can fix this if I change how I declare the array inside the function from declare -a anArray=("${!1}") to your "local" idiom of local anArray=("${!1}").

So, this code

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

testArrayArg3 anArray[@]

works:

testArrayArg3: a b c

~~~~~~~~~~

OK, so the local anArray=("${!1}") function array arg declaration idiom seems to work.

This idiom is mentioned in that SO link that I mentioned above in a hidden comment under Ken Bertelson's answer. To see it, click on the "show 3 more" link and check out Mike Q's comment.

Is it every bit as good as the declare -a anArray=("${!1}") idiom, or does it have drawbacks of its own?

I have some critical code that depends on passing arrays to bash functions, so I really need to get this straight.

Community
  • 1
  • 1
HaroldFinch
  • 762
  • 1
  • 6
  • 17