Passing Array to Function in Bash shell



As much as I love bash, it is mostly casts and spells and not much set logic.
I have the following problem I cannot seem to solve in a logical way so I hope a wizard can help me.

I paste the function and main program below.
Problem is, is that if I run the main program as shown then it works, but when I change a and b as described in the second Main Program example it doesnt work ! ?
Well so much for calling it a function… Functions needs to isolate variables internally which bash seems to break by default, compared to higher level languages, but I cannot get a solution to this peculiarity why just changing the variable names, the answer returned is different. I cannot use local assigns in the function on arrays either to force the function to at least conform to the definition of a function in programming as it is not allowed on arrays it seems.
Anyway , below is the example demonstrating the issue. Solution should be simple as this is a simple issue.

f_CoordinateCombineTwoArrays () {
# Components of a and b is joined into a coordinate (a_i,b_i) and stored in array c
# a,b are nx1 arrays while the result c is an nx2 matrix    
#a=(0 1 2 3 4)
#b=(1 2 3 4 5)
for((i=0;i<${#a[@]};i++));    #Automatically sizes the loop according to #of elements
    for ((j=0;j<${#b[@]};j++)) #Ditto

for i in ${c[@]}
    echo $i

# ---------  Main Program

a=(0 1 2 3 4)
b=(1 2 3 4 5)

f_CoordinateCombineTwoArrays $a $b

#Replacing the Main Program above with the following,The program fails. -----------------------------------------

# ---------  Main Program

x=(0 1 2 3 4)
y=(1 2 3 4 5)

f_CoordinateCombineTwoArrays $x $y




when first called the function uses $a and $b (not the entire arrays) which are respectively ${a[0]} and ${b[0]}, and then uses a and b arrays.

at its second call, the function uses first values (index 0) of x and y arrays, but still uses a and b arrays inside.

you could use nameref (if I understood correctly what your intentions are) :

$ myFunc() { declare -n a=$1; for i in ${a[@]}; do echo "$i"; done;}                                                                                                                                                                  
$ array=( abc def ghi )                                                                                                                                                                                                               
$ myFunc array                                                                                                                                                                                                                        


Thank you for your kind response.
I was afraid it is something like that.
I will work through your proposal which is clear and easy, but I will have to test how well the function variables are isolated.
Calling this structure a Function is really misleading in bash. Is there any way I can completely isolate the variables inside the function so they do not become global ( as the strict definition of a Function is which is broken in batch by default ) ?
It cannot even be called a procedure and should rather be called a routine, the latter which has exposed variables inside the routine when called.
It is an unfortunate name to give this routine the name Function as it is strictly definitely not a function.

So, is there any sure way I can adopt to make sure that I can create a true Function I can use in future, meaning per definition that all internal variables used in the Function are completely isolated globally and that the only globally visible object from the function is the Result returned.

I know I am trying to bend bash to be more strict, but it will really help me to write functions in this way according to the strict definition of a Function, as it creates a lot of chaos with all these glovbal variables from inside the function as my example clearly shows.

Historically functions were created to effect variable isolation so that you sdo not have to call distinct outside programs. It seems that with bash the only possible way to impliment a Function is with a discreetly different program, which is cumbersome. So calling this a Function in bash is quite a wild misrepresentation imo (meant kindly).
I will appreciate it if you could show me how to isolate all function internal variables totally from the remainder of the program.



I tried what you proposed, but the variables a and b inside the function which are now assigned are still globally influenced. So this doesnt solve the problem.
I did mention local assigns in my original post which is basically what you did, but the variables a and b are still not isolated as the following script shows.

myFunc() {
declare -n a=$1;
declare -n b=$2;
for i in ${a[@]};
for j in ${b[@]};
echo “$i,$j”;

#—Main Program
a=( 1 2 3 )
b=( 4 5 5 )
myFunc a b

Terminal output:
warning: a: circular name reference

What I want is a way to work with bash functions by which the bash variables are totally isolated from the remaining global program. So a variable A used in the function is not detected and is different from a variable A in the remainder of the program outside the function. If I can get a way to do this, it will sure clean up problems I have in large bash programs.

  1. Ok it is obvious that all variables passed to a function can be made exclusive by default transport referring to them as $1 …$2 …$n as they are received. If it is assigned to a variable by nam, then that variable must be assigned in the headers of the function and then the variable needs be reset
    after its final use in the function.
    That is then a fair solution and to create isolation for passed variables means just that … dont rename the $1 … $n variables as far as you can and reset them when finished using them in the function.

  2. That then remains how other variables inside the function and not passed to the function can be made exclusive to the function and isolated from the global program, not being able to access from the Global program.
    One way is probably to also assign all the Global variables in the headers of the Global part of the script as is e.g. done in Delphi. That way, if I want to reassign those variables in the function, I will at least get an error message. At least that way I cannot reintroduce any variables unless they are new and that is sort of an acceptable solution.

  3. Then finally what remains is how to make the Global program not being able to access any of the function variables data EXCEPT what is returned by the function. e.g. if a Function contains variable VAR, then if I do $VAR in the global section of the program, then it should just exit with the default empty variable (or preferable … unusable error message), but by (1) & (2) above luckily then I cannot globally set it to a value as it will give me an error which is great. That is all that remains to give me a good half-way solution. (which is what makes bash pleasing sometimes in a wacky way)

So what this is about is creating a reliable Function structure that wont byte you later as a script grows. You already helped me somewhat to formulate a solution myself, with your views, so only part (3) I mention here is remaining as the problem is now reduced to that.


if you call nameref by the same name as the array, of course, that will cause troubles !
even if you make it local (see help local): what array will bash parse in the for loop? the global array, or the locale nameref ?


Well that is the problem right ?
If the Function actually worked by the definition of a classical function then your question above would not even have to be asked. That question is really the core of the problem.
My answer is basically, it depends on what I am writing on that given day. I cant really give an either or. If however it was really a strict function, then I always had to do it ONE way, which would be really constructive.

So I cant really give an answer unless the following in the manual is actually true,…which I seriously doubt from my own experiments.

"Variables local to the function may be declared with the local builtin. These variables are visible only to the function and the commands it invokes. "

The above would have been super if bash Functions actually worked that way, but either the switch is broken or they never implemented it right.

I will think about this and try to formulate a structure that cleans up the Function behavior for me in Bash and post it back again.

Thanks for your help. You did help a lot to make me think in the right direction.


I have a feeling you are trying to look at bash like it is another language, with that being said you can make these changes but I think what you should do is make them global as mentioned and then create local versions in some way or something. I do see your point in doing it this way but it seems a little tortured for bash.

Anyway this kind of change worked for me :slight_smile:

f_CoordinateCombineTwoArrays () {

   local a=( $(echo "$1") )
   local b=( $(echo "$2") )

for((i=0; i<${#a[@]}; i++));    
    for ((j=0;j<${#b[@]};j++)) #Ditto

for i in ${c[@]}
    echo $i    
declare -l x=(0 1 2 3 4)
declare -l y=(1 2 3 4 5)

f_CoordinateCombineTwoArrays "$(echo ${x[@]})" "$(echo ${y[@]})"


Thanks but I did solve it by the way I presented in my last post.