Passing multiple distinct arrays to a shell function

后端 未结 2 1698
醉话见心
醉话见心 2020-12-15 06:49

Because shells other than ksh do not support pass-by-reference, how can multiple arrays be passed into a function in bash without using global variables, and in a way which

相关标签:
2条回答
  • 2020-12-15 06:56

    Can also be done using eval:

    declare -a a=( "aa bb" 123 '$ $ $' )
    declare -a b=( "bb cc" 456 '###' )
    
    printf "\n%s\n" 'a before sub:'
    printf "'%s'\n" "${a[@]}"
    printf "\n%s\n" 'b after sub:'
    printf "'%s'\n" "${b[@]}"
    
    
    sub ()
    {
      eval a0=\${$1[0]}                     # get value a[0]
      eval b1=\${$2[1]}                     # get value b[1]
      echo "a[0] = '$a0'"
      echo "b[1] = '$b1'"
    
      eval $1[0]='a---a'                    # set value a[0]
      eval $2[1]=999                        # set value b[1]
    
    } # ----------  end of function sub  ----------
    
    sub a b     # call function sub
    
    printf "\n%s\n" 'a after sub:'
    printf "'%s'\n" "${a[@]}"
    printf "\n%s\n" 'b after sub:'
    printf "'%s'\n" "${b[@]}"
    

    The output:

    a before sub:
    'aa bb'
    '123'
    '$ $ $'
    
    b after sub:
    'bb cc'
    '456'
    '###'
    a[0] = 'aa bb'
    b[1] = '456'
    
    a after sub:
    'a---a'
    '123'
    '$ $ $'
    
    b after sub:
    'bb cc'
    '999'
    '###'
    
    0 讨论(0)
  • 2020-12-15 07:15

    Since bash 4.3

    As of 2016, modern bash supports pass-by-reference (a.k.a nameref attribute) as:

    demo_multiple_arrays() {
      local -n _array_one=$1
      local -n _array_two=$2
      printf '1: %q\n' "${_array_one[@]}"
      printf '2: %q\n' "${_array_two[@]}"
    }
    
    array_one=( "one argument" "another argument" )
    array_two=( "array two part one" "array two part two" )
    
    demo_multiple_arrays array_one array_two
    

    See also declare -n in the man page.


    Before bash 4.3

    This can be done safely by using a calling convention which puts number-of-arguments before each array, as such:

    demo_multiple_arrays() {
      declare -i num_args array_num;
      declare -a curr_args;
      while (( $# )) ; do
        curr_args=( )
        num_args=$1; shift
        while (( num_args-- > 0 )) ; do
          curr_args+=( "$1" ); shift
        done
        printf "$((++array_num)): %q\n" "${curr_args[@]}"
      done
    }
    

    This can then be called as follows:

    array_one=( "one argument" "another argument" )
    array_two=( "array two part one" "array two part two" )
    demo_multiple_arrays \
      "${#array_one[@]}" "${array_one[@]}" \
      "${#array_two[@]}" "${array_two[@]}"
    
    0 讨论(0)
提交回复
热议问题