如何将数组作为参数传递给bash函数?
注意:在Stack Overflow上找不到答案后,我自己发布了一个有点粗糙的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。如果有人知道更好的方法,请在这里添加。
如何将数组作为参数传递给bash函数?
注意:在Stack Overflow上找不到答案后,我自己发布了一个有点粗糙的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。如果有人知道更好的方法,请在这里添加。
当前回答
只是添加到接受的答案,因为我发现如果数组内容是这样的,它就不能很好地工作:
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©
其他回答
尽管它很丑,但这里有一个变通方法,只要你没有显式地传递一个数组,而是一个对应于数组的变量:
function passarray()
{
eval array_internally=("$(echo '${'$1'[@]}')")
# access array now via array_internally
echo "${array_internally[@]}"
#...
}
array=(0 1 2 3 4 5)
passarray array # echo's (0 1 2 3 4 5) as expected
我相信有人可以提出一个更清晰的思想实现,但我发现这是一个更好的解决方案,而不是传递一个数组作为“{array[@]”},然后在内部使用array_inside=(“$@”)访问它。当存在其他位置/getopts参数时,这就变得复杂了。在这些情况下,我必须首先确定,然后使用shift和数组元素删除的某种组合来删除与数组不关联的参数。
纯粹主义者可能会认为这种方法违反了语言,但从实用主义的角度来说,这种方法为我省去了很多痛苦。在一个相关的主题中,我还使用eval将一个内部构造的数组赋值给一个根据我传递给函数的参数target_varname命名的变量:
eval target_varname =美元”($ {array_inside[@]})”
希望这能帮助到一些人。
这里的基本问题是,设计/实现数组的bash开发人员真的把事情搞砸了。他们认为${array}只是${array[0]}的简称,这是一个严重的错误。特别是当您认为${array[0]}没有意义并且如果数组类型是关联的,则计算结果为空字符串时。
Assigning an array takes the form array=(value1 ... valueN) where value has the syntax [subscript]=string, thereby assigning a value directly to a particular index in the array. This makes it so there can be two types of arrays, numerically indexed and hash indexed (called associative arrays in bash parlance). It also makes it so that you can create sparse numerically indexed arrays. Leaving off the [subscript]= part is short hand for a numerically indexed array, starting with the ordinal index of 0 and incrementing with each new value in the assignment statement.
因此,${array}应该计算为整个数组,索引和所有。它的求值应该是赋值语句的倒数。任何计算机科学专业的三年级学生都应该知道这一点。在这种情况下,这段代码将完全按照你所期望的那样工作:
declare -A foo bar
foo=${bar}
然后,按值将数组传递给函数并将一个数组分配给另一个数组将按照shell语法的其余部分执行。但是因为他们做得不对,赋值操作符=对数组不起作用,并且数组不能通过值传递给函数或子shell或一般的输出(echo ${array}),而没有代码来仔细检查它。
因此,如果做得正确,那么下面的例子将显示数组在bash中的用处可以大大提高:
simple=(first=one second=2 third=3)
echo ${simple}
结果输出应该是:
(first=one second=2 third=3)
然后,数组可以使用赋值操作符,并按值传递给函数甚至其他shell脚本。通过输出到文件很容易存储,也很容易从文件加载到脚本中。
declare -A foo
read foo <file
可惜的是,一个顶级的bash开发团队让我们失望了。
因此,要将数组传递给函数,实际上只有一个选项,那就是使用nameref特性:
function funky() {
local -n ARR
ARR=$1
echo "indexes: ${!ARR[@]}"
echo "values: ${ARR[@]}"
}
declare -A HASH
HASH=([foo]=bar [zoom]=fast)
funky HASH # notice that I'm just passing the word 'HASH' to the function
将导致以下输出:
indexes: foo zoom
values: bar fast
由于这是通过引用传递的,所以也可以在函数中为数组赋值。是的,被引用的数组必须具有全局作用域,但考虑到这是shell脚本,这应该不是太大的问题。要将一个关联或稀疏索引数组按值传递给一个函数,需要将所有索引和值作为单个字符串扔到参数列表中(如果是一个大数组,则不太有用),如下所示:
funky "${!array[*]}" "${array[*]}"
然后在函数内部写一堆代码来重新组装数组。
只是添加到接受的答案,因为我发现如果数组内容是这样的,它就不能很好地工作:
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©
我的简短回答是:
function display_two_array {
local arr1=$1
local arr2=$2
for i in $arr1
do
echo "arrary1: $i"
done
for i in $arr2
do
echo "arrary2: $i"
done
}
test_array=(1 2 3 4 5)
test_array2=(7 8 9 10 11)
display_two_array "${test_array[*]}" "${test_array2[*]}"
需要注意的是${test_array[*]}和${test_array2[*]}应该被""包围,否则就会失败。
现代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属性“不能应用于数组变量”,但它可以?