以下帖子解决方案按预期工作:
因此 - 从他的回答来看:
function copyFiles() {
arr=("$@")
for i in "${arr[@]}";
do
echo "$i"
done
}
array=("one 1" "two 2" "three 3")
copyFiles "${array[@]}"
写这篇文章的原因是如果发生以下情况怎么办:
copyFiles "${array[@]}" "Something More"
copyFiles "Something More" "${array[@]}"
问题:我确实意识到发送的参数,当收到它们时,函数中的参数如何 - 它们实际上是合并的 - 因此,$1
“$2
数组”参数不再按预期工作整合与另一个论点
我已经做了一项研究:
可悲的typeset -n
是不是工作
并在:
做不是按预期工作 - 在该答案中,有一条评论表明存在问题 - 带有演示测试/验证的链接 - 关于${#array[@]}
函数内的数组大小 ( ) 不同。
那么如何实现这个目标呢?
答案1
不可能像这样传递数组作为参数。即使看起来你这样做了,但它并没有像你期望的那样工作
您的外壳(例如此处bash
:)将扩展"${array[@]}"
到各个项目前执行函数!
所以这
copyFiles "Something More" "${array[@]}"
实际上会打电话
copyFiles "Something More" "one 1" "two 2" "three 3"
因此,在函数内部不可能将数组与其他参数区分开。
(你可以 添加对数组的引用,但我反对使用它,因为它似乎不太便携,而且如果没有必要,您也不会想要混合范围)。
您可以使用shift
,例如
copyFiles() {
var1=$1
shift
for i in "$@"; do ... ; done
}
(注意,这arr=("$@")
是多余的,$@
已经是一个数组,你甚至不需要指定"$@"
,你也可以使用for i; do ...; done
)
或用类似的东西解析参数getopts
。
答案2
你不能直接做到这一点,无论如何也不是很好。数组确实不是 Bash 中的一流对象,如果您需要做这样的事情,您可能需要真正考虑切换到真正的编程语言......
核心问题是"${array[@]}"
只是扩展到数组的所有元素(列表)(忘记索引!),而不是实际给出数组本身。
当然有一些解决方法,但我不确定我会称它们非常好。但你可以...
使用一些分隔符:
func "non-array" "arguments" :: "${array[@]}"
这本质上就是 GNU Parallel 所做的事情,但缺点是您需要决定一些不能用作实际参数的值。 (或者某种逃避它的方法,这可能会更糟。)您必须扫描参数列表才能找到分隔符。
添加参数来告知列表的长度:
func 1 "non-array argument" "${#array[@]}" "${array[@]}"
这应该足够通用,可以传递任何有效值,但如果它开始让您回想起 C 中手动内存处理的痛苦回忆,我不会责怪您。在另一端解析它也可以作为任何疯狂到想要这样做的人的练习。
改为按名称传递数组。
您可能想使用 namerefs,例如:
fun() { local _arrayname="$1" local -n _ref="$1" printf "array '%s' has %d members\n" "$_arrayname" "${#_ref[@]}" printf "member at index #2 is '%s'\n" "${_ref[2]}" } asdf=(one too tree) fun asdf
您也可以尝试使用
${!p}
间接语法,但是 IIRC,使用该语法对数组进行索引更困难。当然,两者都是不可移植的,因此您最终可能会陷入 Bash 困境,但 Bash 至少从 4.4 版本开始支持 namerefs,因此在大多数情况下这不应该成为问题。namerefs 的问题是命名空间冲突,您无法将名为
_arrayname
或的数组传递_ref
给上述函数。