0

In the code snippet below, I found that, when trying to pass multiple arrays to a function in Bash, I am able to do so using the syntax in my first example, but only if:

  1. The array variable names are prefixed with an underscore (_)
  2. The array variable names are otherwise identically named in the receiving function as the calling function
function list_arrays {
    local _array_one=$1
    local _array_two=$2
    for ip in "${array_one[@]}"; do
        echo "$ip"
    done
    for node in "${array_two[@]}"; do
        echo "$node"
    done
}

function main {
    local array_one=( 1 2 3 4 5 )
    local array_two=( one two three four five )
    list_arrays "${array_one[@]}" "${array_two[@]}"
}

main

Output:

1
2
3
4
5
one
two
three
four
five

Changing the example slightly to remove the underscores...

#!/bin/bash

function list_arrays {
    local array_one=$1
    local array_two=$2
    for ip in "${array_one[@]}"; do
        echo "$ip"
    done
    for node in "${array_two[@]}"; do
        echo "$node"
    done
}

function main {
    local array_one=( 1 2 3 4 5 )
    local array_two=( one two three four five )
    list_arrays "${array_one[@]}" "${array_two[@]}"
}

main

Output:

1
2

One last iteration to change the name of the array variables in the list_arrays function

#!/bin/bash

function list_arrays {
    local _array_first=$1
    local _array_second=$2
    for ip in "${_array_first[@]}"; do
        echo "$ip"
    done
    for node in "${_array_second[@]}"; do
        echo "$node"
    done
}

function main {
    local array_one=( 1 2 3 4 5 )
    local array_two=( one two three four five )
    list_arrays "${array_one[@]}" "${array_two[@]}"
}

main

Output:


(no output)

The behavior is extremely convenient but I want to understand what I'm doing before I use this in production scripts. At first I thought this might be related to pass-by-reference. However, this syntax works in Bash 4.1 which seems to be before pass-by-reference was added.

2
  • did you try to declare the variable as an array (local -a array_first=$1)?
    – rr0ss0rr
    Apr 22, 2020 at 1:01
  • Are you sure there is no output in the third case? I think what you are seeing in the first two cases is the consequence of dynamic scoping. I would expect the same for any names for the local variables in list_arrays that are distinct from those in main. Apr 22, 2020 at 1:18

1 Answer 1

2

The code is working as expected:

function main {
    local array_one=( 1 2 3 4 5 )
    local array_two=( one two three four five )
    list_arrays "${array_one[@]}" "${array_two[@]}"
}

The arguments passed are not two arrays, but 1 2 3 4 5 one two three four five.

The function list_arrays prints, not the arguments passed but the defined local array_one and local array_two in function main

You can see this by changing your code to

function list_arrays {
    # no variable definition
    for ip in "${array_one[@]}"; do
        echo "$ip"
    done
    for node in "${array_two[@]}"; do
        echo "$node"
    done
}

function main {
    local array_one=( 1 2 3 4 5 )
    local array_two=( one two three four five )
    # no arguments passed
    list_arrays
}

Output:

1
2
3
4
5
one
two
three
four
five

The variables local _array_one=$1 and local _array_two=$2 are not really used at all in your code.


When you redefine the variables, as in

function list_arrays {
    local array_one=$1 # overwrites main's array_one
    local array_two=$2 # overwrites main's array_two
    for ip in "${array_one[@]}"; do
        echo "$ip"
    done
    for node in "${array_two[@]}"; do
        echo "$node"
    done
}

function main {
    local array_one=( 1 2 3 4 5 )
    local array_two=( one two three four five )

    # arguments passed are 1 2 3 4 5 one two three four five
    list_arrays "${array_one[@]}" "${array_two[@]}"

}

now array_one is equal to the first argument, 1, and array_two to the second argument, 2, so the output is

1
2
2
  • To follow up and make sure I'm understanding you correctly, does this mean that local array_one and local array_two are global variables (despite being declared local)? I'm trying to understand how list_arrays has access to them without them being passed or defined in that function.
    – user407898
    Apr 22, 2020 at 1:37
  • They are local in main, and as list_arrays is inside main, it is in the same (local) scope. Apr 22, 2020 at 1:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .