如何将数组作为参数传递给bash函数?

注意:在Stack Overflow上找不到答案后,我自己发布了一个有点粗糙的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。如果有人知道更好的方法,请在这里添加。


当前回答

现代bash(显然是4.3或更高版本)允许通过引用传递数组。我将在下面展示。如果您希望手动序列化和反序列化数组,请参阅我在这里对bash常规“索引”数组和bash关联数组的回答。但是,如下所示,通过引用传递数组要简单得多,也更简洁,所以我现在推荐这样做。

下面的代码也可以在我的eRCaGuy_hello_world repo中在线获得:array_pass_as_bash_parameter_by_reference.sh。另请参阅这里的示例:array_pass_as_bash_parameter_2_associate .sh。

下面是一个常规bash数组的演示:

function foo {
    # declare a local **reference variable** (hence `-n`) named `data_ref`
    # which is a reference to the value stored in the first parameter
    # passed in
    local -n data_ref="$1"
    echo "${data_ref[0]}"
    echo "${data_ref[1]}"
}

# declare a regular bash "indexed" array
declare -a data
data+=("Fred Flintstone")
data+=("Barney Rubble")
foo "data"

样例输出:

摩登原始人 巴尼废墟

...下面是一个关联bash数组的演示(例如:bash哈希表,“字典”或“无序映射”):

function foo {
    # declare a local **reference variable** (hence `-n`) named `data_ref`
    # which is a reference to the value stored in the first parameter
    # passed in
    local -n data_ref="$1"
    echo "${data_ref["a"]}"
    echo "${data_ref["b"]}"
}

# declare a bash associative array
declare -A data
data["a"]="Fred Flintstone"
data["b"]="Barney Rubble"
foo "data"

样例输出:

摩登原始人 巴尼废墟

引用:

我从@Todd Lehman的回答中修改了上面的代码示例:如何在Bash中将关联数组作为参数传递给函数? 请参见我的手动序列化/反序列化答案 并在这里查看我的后续问题:为什么man bash页面声明declare和local -n属性“不能应用于数组变量”,但它可以?

其他回答

注:这是我在Stack Overflow上找不到答案后自己发布的粗略的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。不久之后,Ken发布了他的解决方案,但我把我的保留在这里作为“历史”参考。

calling_function()
{
    variable="a"
    array=( "x", "y", "z" )
    called_function "${variable}" "${array[@]}"
}

called_function()
{
    local_variable="${1}"
    shift
    local_array=("${@}")
}

你可以像这样传递多个数组作为参数:

takes_ary_as_arg()
{
    declare -a argAry1=("${!1}")
    echo "${argAry1[@]}"

    declare -a argAry2=("${!2}")
    echo "${argAry2[@]}"
}
try_with_local_arys()
{
    # array variables could have local scope
    local descTable=(
        "sli4-iread"
        "sli4-iwrite"
        "sli3-iread"
        "sli3-iwrite"
    )
    local optsTable=(
        "--msix  --iread"
        "--msix  --iwrite"
        "--msi   --iread"
        "--msi   --iwrite"
    )
    takes_ary_as_arg descTable[@] optsTable[@]
}
try_with_local_arys

将回声:

sli4-iread sli4-iwrite sli3-iread sli3-iwrite  
--msix  --iread --msix  --iwrite --msi   --iread --msi   --iwrite

编辑/注释:(摘自下面的评论)

descTable和optsTable作为名称传递,并在函数中展开。因此,在作为参数给出时不需要$。 注意,即使用local定义了descTable等,这仍然有效,因为locals对于它们调用的函数是可见的。 !在$ {!1}展开arg 1变量。 声明-a只是使索引数组显式,这不是严格必要的。

function aecho {
  set "$1[$2]"
  echo "${!1}"
}

例子

$ foo=(dog cat bird)

$ aecho foo 1
cat

现代bash(显然是4.3或更高版本)允许通过引用传递数组。我将在下面展示。如果您希望手动序列化和反序列化数组,请参阅我在这里对bash常规“索引”数组和bash关联数组的回答。但是,如下所示,通过引用传递数组要简单得多,也更简洁,所以我现在推荐这样做。

下面的代码也可以在我的eRCaGuy_hello_world repo中在线获得:array_pass_as_bash_parameter_by_reference.sh。另请参阅这里的示例:array_pass_as_bash_parameter_2_associate .sh。

下面是一个常规bash数组的演示:

function foo {
    # declare a local **reference variable** (hence `-n`) named `data_ref`
    # which is a reference to the value stored in the first parameter
    # passed in
    local -n data_ref="$1"
    echo "${data_ref[0]}"
    echo "${data_ref[1]}"
}

# declare a regular bash "indexed" array
declare -a data
data+=("Fred Flintstone")
data+=("Barney Rubble")
foo "data"

样例输出:

摩登原始人 巴尼废墟

...下面是一个关联bash数组的演示(例如:bash哈希表,“字典”或“无序映射”):

function foo {
    # declare a local **reference variable** (hence `-n`) named `data_ref`
    # which is a reference to the value stored in the first parameter
    # passed in
    local -n data_ref="$1"
    echo "${data_ref["a"]}"
    echo "${data_ref["b"]}"
}

# declare a bash associative array
declare -A data
data["a"]="Fred Flintstone"
data["b"]="Barney Rubble"
foo "data"

样例输出:

摩登原始人 巴尼废墟

引用:

我从@Todd Lehman的回答中修改了上面的代码示例:如何在Bash中将关联数组作为参数传递给函数? 请参见我的手动序列化/反序列化答案 并在这里查看我的后续问题:为什么man bash页面声明declare和local -n属性“不能应用于数组变量”,但它可以?

这条即使有空格也适用:

format="\t%2s - %s\n"

function doAction
{
  local_array=("$@")
  for (( i = 0 ; i < ${#local_array[@]} ; i++ ))
    do
      printf "${format}" $i "${local_array[$i]}"
  done
  echo -n "Choose: "
  option=""
  read -n1 option
  echo ${local_array[option]}
  return
}

#the call:
doAction "${tools[@]}"