如何将数组作为参数传递给bash函数?
注意:在Stack Overflow上找不到答案后,我自己发布了一个有点粗糙的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。如果有人知道更好的方法,请在这里添加。
如何将数组作为参数传递给bash函数?
注意:在Stack Overflow上找不到答案后,我自己发布了一个有点粗糙的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。如果有人知道更好的方法,请在这里添加。
当前回答
你可以像这样传递多个数组作为参数:
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只是使索引数组显式,这不是严格必要的。
其他回答
评论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
只是添加到接受的答案,因为我发现如果数组内容是这样的,它就不能很好地工作:
RUN_COMMANDS=(
"command1 param1... paramN"
"command2 param1... paramN"
)
在这种情况下,数组的每个成员都被分割,所以函数看到的数组等价于:
RUN_COMMANDS=(
"command1"
"param1"
...
"command2"
...
)
为了让这种情况工作,我发现的方法是将变量名传递给函数,然后使用eval:
function () {
eval 'COMMANDS=( "${'"$1"'[@]}" )'
for COMMAND in "${COMMANDS[@]}"; do
echo $COMMAND
done
}
function RUN_COMMANDS
只是我的2©
注:这是我在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=("${@}")
}
DevSolar的回答有一点我不理解(也许他有特定的理由这么做,但我想不出一个):他根据位置参数一个元素一个元素地迭代设置数组。
一个更简单的解释是
called_function()
{
...
# do everything like shown by DevSolar
...
# now get a copy of the positional parameters
local_array=("$@")
...
}