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

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


当前回答

这条即使有空格也适用:

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[@]}"

其他回答

评论Ken Bertelson的解决方案并回答Jan Hettich:

它是如何工作的

try_with_local_arys()函数中的takes_ary_as_arg descTable[@] optsTable[@]行发送:

This is actually creates a copy of the descTable and optsTable arrays which are accessible to the takes_ary_as_arg function. takes_ary_as_arg() function receives descTable[@] and optsTable[@] as strings, that means $1 == descTable[@] and $2 == optsTable[@]. in the beginning of takes_ary_as_arg() function it uses ${!parameter} syntax, which is called indirect reference or sometimes double referenced, this means that instead of using $1's value, we use the value of the expanded value of $1, example: baba=booba variable=baba echo ${variable} # baba echo ${!variable} # booba likewise for $2. putting this in argAry1=("${!1}") creates argAry1 as an array (the brackets following =) with the expanded descTable[@], just like writing there argAry1=("${descTable[@]}") directly. the declare there is not required.

注意:值得一提的是,使用这个括号形式的数组初始化根据IFS或内部字段分隔符初始化新数组,默认为制表符、换行符和空格。在这种情况下,因为它使用[@]符号,所以每个元素都被看作是被引用的(与[*]相反)。

我对它的预订

在BASH中,局部变量作用域是当前函数和从它调用的每个子函数,这转化为这样一个事实,takes_ary_as_arg()函数“看到”那些descTable[@]和optsTable[@]数组,因此它是工作的(见上述解释)。

既然如此,为什么不直接看看这些变量本身呢?这就像写在这里:

argAry1=("${descTable[@]}")

参见上面的解释,它只是根据当前的IFS复制descTable[@]数组的值。

总之

从本质上讲,这只是过去,没有任何价值——和往常一样。

我还想强调Dennis Williamson上面的评论:稀疏数组(没有所有键定义的数组-其中有“孔”)不会像预期的那样工作-我们会失去键并“压缩”数组。

话虽如此,我确实看到了泛化的价值,因此函数可以在不知道名称的情况下获得数组(或副本):

对于~“拷贝”:这个技术已经足够好了,只是需要注意,索引(键)已经没有了。 对于真实副本: 我们可以对键使用eval,例如: Eval本地键=(\${!$1})

然后循环使用它们来创建副本。 注:这里!不是使用它之前的间接/双重求值,而是在数组上下文中返回数组下标(键)。

当然,如果我们要传递descTable和optsTable字符串(不带[@]),我们可以在eval中使用数组本身(如通过引用)。用于接受数组的泛型函数。

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

例子

$ foo=(dog cat bird)

$ aecho foo 1
cat

要求:在数组中查找字符串的函数。 这是DevSolar解决方案的一个轻微简化,因为它使用传入的参数而不是复制它们。

myarray=('foobar' 'foxbat')

function isInArray() {
  local item=$1
  shift
  for one in $@; do
    if [ $one = $item ]; then
      return 0   # found
    fi
  done
  return 1       # not found
}

var='foobar'
if isInArray $var ${myarray[@]}; then
  echo "$var found in array"
else
  echo "$var not found in array"
fi 

现代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[@]}"