如果我理解正确,如果该值尚未在数组中,则您想将值附加到数组中,但棘手的部分是 数组名称 被传递给函数。
方法一
一种可能性是从不同的角度看待问题:您可以将要插入的值和完整数组传递给函数,该函数将设置一个全局变量,您将在执行后恢复该变量。对于我们的测试示例,我们将使用:
array=( hello world "how are you today?" )
我们将尝试插入test 和hello(这样hello 就不会被插入):
f() {
# This function will set the global variable _f_out to an array obtained from
# the positional parameters starting from position 2, with $1 appended if and
# only if $1 doesn't appear in the subsequent positional parameters
local v=$1 i
shift
_f_out=( "$@" )
for i; do [[ $i = $v ]] && return; done
_f_out+=( "$v" )
}
让我们使用它:
$ array=( hello world "how are you today?" )
$ f test "${array[@]}"
$ array=( "${_f_out[@]}" )
$ printf '%s\n' "${array[@]}"
hello
world
how are you today?
test
$ f hello "${array[@]}"
$ array=( "${_f_out[@]}" )
$ printf '%s\n' "${array[@]}"
hello
world
how are you today?
test
有效。
备注。我使用了for i; do。这是for i in "$@"; do 的一个不错的快捷方式。
方法二
您真的很想摆弄 simili-pointers 并在适当的位置进行附加(这并不真正符合 Bash 的精神——这就是它有点笨拙的原因)。工具是使用printf 和-v 选项:来自help printf:
-v var assign the output to shell variable VAR rather than
display it on the standard output
好处是它也适用于数组字段。
警告:您可能会看到使用eval 的其他方法。像瘟疫一样避开它们!
f() {
local array_name=$2[@] i
local array=( "${!array_name}" )
for i in "${array[@]}"; do [[ $i = $1 ]] && return; done
# $1 was not found in array, so let's append it
printf -v "$2[${#array[@]}]" '%s' "$1"
}
让我们试试吧:
$ array=( hello world "how are you today?" )
$ f test array
$ printf '%s\n' "${array[@]}"
hello
world
how are you today?
test
$ f hello array
$ printf '%s\n' "${array[@]}"
hello
world
how are you today?
test
它也有效。
注意。 使用这两种方法,您可以很容易地获得函数的return 代码,例如,如果值被插入,0(成功),1(失败)如果值已经存在(或相反)——适应很简单,留作练习。这在方法 1 中可能很有用,可用于确定是否需要将 array 更新为返回值 _f_out。在这种情况下,您甚至可以稍微修改 f,以便当值已经在数组中时它甚至不会设置 _f_out。
警告。 在显示的两种方法中,我假设您的数组具有从 0 开始的连续索引(即非稀疏数组)。我认为这是一个安全的假设;但如果不是这种情况,这些方法将被破坏:第一个将(重新分配后)将数组转换为非稀疏数组,第二个可能会覆盖字段(如数组a,@987654344 @ 扩展为数组中元素的数量,而不是数组中找到的最高索引 + 1)。