3

I have this array:

PARAMETERS_OF_COMPONENTS[1]="component1"
PARAMETERS_OF_COMPONENTS[2]="component21 component22 component23"
PARAMETERS_OF_COMPONENTS[3]="component3"
PARAMETERS_OF_COMPONENTS[4]="component41 component42 component43"

I want to pass that array to this function:

foo()
{
    local param1="$1"
    local param2="$2"
    local array_param="$3"
    . . .

    echo "${PARAMETERS_OF_COMPONENTS[@]}"
}

When I pass an array in this manner:

foo "$param1" "$param2" "${PARAMETER_OF_COMPONENTS[@]}"

then function just prints:

component1

Also, I've been tried couple of other methods to pass array, but I still didn't find right solution.

How can I pass correctly array to function? Also, solution must be compatible with Dash (at least without bashisms).

UPD @Kusalananda explained to me that Dash doesn't support an arrays. Thank's for clarify.

I will ask another one. How can I pass many parameters to function without pass it directly in manner $1,$2 ... and don't involve global variables? I have several ideas, but I would to listen yours approaches?

My task is to move function from one file to another, but that function uses global variables. I don't want to use global variables. So how to do this in the most right way?

2
  • dash does not support arrays.
    – Kusalananda
    May 21, 2018 at 13:44
  • @Kusalananda Thank's for clarify! I rephrase my question. May 21, 2018 at 13:46

1 Answer 1

4

In an sh shell that does not support arrays and the local keyword, you may still use $@ as an array in the function. You may pick off the two first arguments with shift 2 and then use $@ which now hold all the rest of the arguments.

foo () {
    arg1=$1
    arg2=$2

    shift 2  # shift $3 into $1, $4 into $2 etc.

    for n in "$@"; do    # or just: for n do
        printf 'Other argument: %s\n' "$n"
        # other code acting on "$n"
    done
}

foo "arg1" "arg2" "arg3" "arg4"

Enclose the body of the function in ( ... ) instead of { ... } to make all variables local, if the function does not need to modify global variables and you don't want to pollute the variable namespace with unnecessary variables.


Using your original data with foo declared as above:

set -- "component1" \
       "component21 component22 component23" \
       "component3" \
       "component41 component42 component43"

foo "$param1" "$param2" "$@"

In a shell that supports arrays and local, you would do the exact same thing (but the function may want to use variables declared as local), and the call might be

foo "arg1" "arg2" "${myarray[@]}"

To pass multiple arrays in bash, I would use a name reference in the function (requires bash release 4.3 or later):

foo () {
   local arg1=$1
   local arg2=$2
   local -n arr1=$3
   local -n arr2=$4

   for n in "${arr2[@]}"; do ...; done
}

foo "arg1" "arg2" myarray1 myarray2

Note that you can't pass an array variable to the function that has the same name as the corresponding name reference variable in the function (I consider this a bug, it works in ksh93).

8
  • Thank's for the answer. I see that foo "arg1" "arg2" "arg3" "arg4" is the most right way for compatibility between bash and dash. I think in this manner too, but I hoped exists more beautiful (from view point) solution. Please, tell me what -n flag mean for the local operator? I didn't find it in man page. (bash 3.2.57). May 21, 2018 at 14:47
  • @YurijGoncharuk I should have said, name references declared with either declare -n or local -n needs a more recent version of bash :-/ I think they were introduced in bash release 4.3.
    – Kusalananda
    May 21, 2018 at 14:57
  • @YurijGoncharuk You could possibly use indirection instead: ${!arr2[@]}, but I haven't tried this with arrays.
    – Kusalananda
    May 21, 2018 at 14:59
  • 1
    I've already tried indirection. It works for my version of bash. May 21, 2018 at 15:00
  • @YurijGoncharuk Good! A name reference is more or less the same thing but without the need for the extra syntactical sugar (the !).
    – Kusalananda
    May 21, 2018 at 15:02

You must log in to answer this question.

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