将多个不同的数组传递给shell函数

Cha*_*ffy 11 bash

因为除了ksh之外的shell不支持pass-by-reference,如何在不使用全局变量的情况下将多个数组传递给bash中的函数,并且允许将任何合法变量内容作为数组元素包含在内(不保留印记)?

Cha*_*ffy 21

自从bash 4.3

截至2016年,现代bash支持pass-by-reference(aka nameref属性):

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
Run Code Online (Sandbox Code Playgroud)

另请参见declare -n手册页.


在bash 4.3之前

这可以通过使用调用约定来安全地完成,该约定在每个数组之前放置参数个数,如下所示:

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
}
Run Code Online (Sandbox Code Playgroud)

然后可以按如下方式调用它:

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[@]}"
Run Code Online (Sandbox Code Playgroud)


小智 5

我找到了一种将多个数组传递给函数的简洁方法。这不是一个完美的解决方案(因为如果数组中的任何元素包含空格,它就不起作用),但我认为分享给像我这样仍然使用 4.3 之前的 Bash 版本的任何人可能会有所帮助。

声明函数:

myFunction()
{
  IFS=' ' read -ra array1 <<< "${1}"
  IFS=' ' read -ra array2 <<< "${2}"
  
  echo "first array (length=${#array1[@]}): ${array1[@]}"
  echo "second array (length=${#array2[@]}): ${array2[@]}"
}
Run Code Online (Sandbox Code Playgroud)

将两个不同的数组传递给函数(作为空格分隔的字符串):

declare -a firstArray=(1 2 3 4 5)
declare -a secondArray=(one two three)

myFunction "${firstArray[*]}" "${secondArray[*]}"
Run Code Online (Sandbox Code Playgroud)

输出:

first array (length=5): 1 2 3 4 5
second array (length=3): one two three
Run Code Online (Sandbox Code Playgroud)

尽管这个解决方案并不完美,但它使我可以更轻松地将其他非数组参数传递给我的函数。(我发现除了其他非数组参数之外,使用嵌套的 while 循环来排序多个数组很快就会变得混乱。)