passing multiple arrays as a parameter in bash

后端 未结 2 1639
猫巷女王i
猫巷女王i 2021-01-26 11:22

I have successfully been able to call a single array as a parameter, but I am having trouble passing through multiple arrays. Here is what I have so far:

callin         


        
2条回答
  •  悲哀的现实
    2021-01-26 11:56

    A function or program's argument list is a single, long array. When you concatenate three different source arrays onto it, the result is still only one argument list, with the contents of those three arrays one after the other.

    There are two solutions. The safest one is to concatenate onto a single argument list and pass arguments by value, with each array prefixed by its length:

    caller() {
        array1=(1   2   3   4)
        array2=(a   b   c   d)
        array3=('!' '@' '#' '$')
    
        callee \
          "${#array1[@]}" "${array1[@]}" \
          "${#array2[@]}" "${array2[@]}" \
          "${#array3[@]}" "${array3[@]}"
    }
    
    callee() {
        # using declare -a makes the values truly local
        # without local or declare they're actually global
        declare -a local_array1=( "${@:1:$1}" ); shift "$(( $1 + 1 ))"
        declare -a local_array2=( "${@:1:$1}" ); shift "$(( $1 + 1 ))"
        declare -a local_array3=( "${@:1:$1}" ); shift "$(( $1 + 1 ))"
    
        printf 'array1 entry: %q\n' "${local_array1[@]}"
        printf 'array2 entry: %q\n' "${local_array2[@]}"
        printf 'array3 entry: %q\n' "${local_array3[@]}"
    }
    

    The other approach is to pass by reference. If you have bash 4.3, you can use a new shell feature called namevars, first implemented by ksh explicitly for this purpose:

    caller() {
        array1=(1   2   3   4)
        array2=(a   b   c   d)
        array3=('!' '@' '#' '$')
    
        callee array1 array2 array3
    }
    
    callee() {
        declare -n local_array1=$1
        declare -n local_array2=$2
        declare -n local_array3=$3
    
        printf 'array1 entry: %q\n' "${local_array1[@]}"
        printf 'array2 entry: %q\n' "${local_array2[@]}"
        printf 'array3 entry: %q\n' "${local_array3[@]}"
    }
    

    However, pass-by-reference is somewhat more fragile: It depends on variable scope being accessible everywhere relevant, and a callee can modify values of the arrays in the caller (indeed, when using the bash-4.3 namevar approach showing here, that behavior is automatic: Any change to local_array1 will also modify array1).

提交回复
热议问题