如何将数组作为参数传递给bash函数?
注意:在Stack Overflow上找不到答案后,我自己发布了一个有点粗糙的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。如果有人知道更好的方法,请在这里添加。
如何将数组作为参数传递给bash函数?
注意:在Stack Overflow上找不到答案后,我自己发布了一个有点粗糙的解决方案。它只允许传递一个数组,并且它是参数列表的最后一个元素。实际上,它根本没有传递数组,而是传递数组元素的列表,这些元素被called_function()重新组装成一个数组,但它对我来说是有效的。如果有人知道更好的方法,请在这里添加。
当前回答
我的简短回答是:
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[*]}应该被""包围,否则就会失败。
其他回答
function aecho {
set "$1[$2]"
echo "${!1}"
}
例子
$ foo=(dog cat bird)
$ aecho foo 1
cat
我的简短回答是:
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[*]}应该被""包围,否则就会失败。
通过一些技巧,您实际上可以将命名参数与数组一起传递给函数。
我开发的方法允许你访问传递给函数的参数,就像这样:
testPassingParams() {
@var hello
l=4 @array anArrayWithFourElements
l=2 @array anotherArrayWithTwo
@var anotherSingle
@reference table # references only work in bash >=4.3
@params anArrayOfVariedSize
test "$hello" = "$1" && echo correct
#
test "${anArrayWithFourElements[0]}" = "$2" && echo correct
test "${anArrayWithFourElements[1]}" = "$3" && echo correct
test "${anArrayWithFourElements[2]}" = "$4" && echo correct
# etc...
#
test "${anotherArrayWithTwo[0]}" = "$6" && echo correct
test "${anotherArrayWithTwo[1]}" = "$7" && echo correct
#
test "$anotherSingle" = "$8" && echo correct
#
test "${table[test]}" = "works"
table[inside]="adding a new value"
#
# I'm using * just in this example:
test "${anArrayOfVariedSize[*]}" = "${*:10}" && echo correct
}
fourElements=( a1 a2 "a3 with spaces" a4 )
twoElements=( b1 b2 )
declare -A assocArray
assocArray[test]="works"
testPassingParams "first" "${fourElements[@]}" "${twoElements[@]}" "single with spaces" assocArray "and more... " "even more..."
test "${assocArray[inside]}" = "adding a new value"
换句话说,您不仅可以通过名称调用参数(这使核心更具可读性),还可以实际传递数组(以及对变量的引用——该特性仅在bash 4.3中有效)!另外,映射的变量都在局部作用域中,就像$1(和其他变量)一样。
实现这一功能的代码非常简单,并且可以在bash 3和bash 4中工作(这是我测试过的唯一版本)。如果你对更多这样的技巧感兴趣,可以让bash开发变得更好更简单,你可以看看我的bash Infinity Framework,下面的代码就是为此目的而开发的。
Function.AssignParamLocally() {
local commandWithArgs=( $1 )
local command="${commandWithArgs[0]}"
shift
if [[ "$command" == "trap" || "$command" == "l="* || "$command" == "_type="* ]]
then
paramNo+=-1
return 0
fi
if [[ "$command" != "local" ]]
then
assignNormalCodeStarted=true
fi
local varDeclaration="${commandWithArgs[1]}"
if [[ $varDeclaration == '-n' ]]
then
varDeclaration="${commandWithArgs[2]}"
fi
local varName="${varDeclaration%%=*}"
# var value is only important if making an object later on from it
local varValue="${varDeclaration#*=}"
if [[ ! -z $assignVarType ]]
then
local previousParamNo=$(expr $paramNo - 1)
if [[ "$assignVarType" == "array" ]]
then
# passing array:
execute="$assignVarName=( \"\${@:$previousParamNo:$assignArrLength}\" )"
eval "$execute"
paramNo+=$(expr $assignArrLength - 1)
unset assignArrLength
elif [[ "$assignVarType" == "params" ]]
then
execute="$assignVarName=( \"\${@:$previousParamNo}\" )"
eval "$execute"
elif [[ "$assignVarType" == "reference" ]]
then
execute="$assignVarName=\"\$$previousParamNo\""
eval "$execute"
elif [[ ! -z "${!previousParamNo}" ]]
then
execute="$assignVarName=\"\$$previousParamNo\""
eval "$execute"
fi
fi
assignVarType="$__capture_type"
assignVarName="$varName"
assignArrLength="$__capture_arrLength"
}
Function.CaptureParams() {
__capture_type="$_type"
__capture_arrLength="$l"
}
alias @trapAssign='Function.CaptureParams; trap "declare -i \"paramNo+=1\"; Function.AssignParamLocally \"\$BASH_COMMAND\" \"\$@\"; [[ \$assignNormalCodeStarted = true ]] && trap - DEBUG && unset assignVarType && unset assignVarName && unset assignNormalCodeStarted && unset paramNo" DEBUG; '
alias @param='@trapAssign local'
alias @reference='_type=reference @trapAssign local -n'
alias @var='_type=var @param'
alias @params='_type=params @param'
alias @array='_type=array @param'
这条即使有空格也适用:
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[@]}"
注:这是我在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=("${@}")
}