Bash-用函数修改数组

时间:2018-08-26 15:13:45

标签: bash

我不明白为什么这个示例脚本不修改array2的内容。似乎我们应该能够通过遍历array1的元素并通过array2的索引将对应的元素设置为等于array1中的元素来将array2设置为等于array1

#!/bin/bash

array1=(1 2 3)
array2=()

modify_array2 () {
#set array2 to be equal to array1 by iterating through array1's 
#elements and setting the corresponding element by index of array2 by 
#to be equal to the element in array1

index=0
declare -a _array1=("${!1}")
declare -a _array2=("${!2}")
for i in "${_array1[@]}"; do
  _array2["$index"]="$i"
  ((index++))
done
}

modify_array2 array1[@] array2[@]
#this should permanently modify array2, however if we print the 
#contents of array2, we get nothing:

for i in "${array2[@]}"; do
  printf "$i\n"
done

输出:

Shellcheck表示以下内容:

第3行: array1 =(1 2 3) ^-SC2034:array1似乎未使用。验证使用情况(或在外部使用时导出)。 没道理,我很明显在以下地方使用它:

modify_array2 array1[@] array2[@]

第11行:   _array2 [“ $ index”] =“ $ i”   ^-SC2034:_array2似乎未使用。验证使用情况(或在外部使用时导出)。

奇数,因为我不是通过在以下位置使用位置参数进行扩展来使用它的:

modify_array2 array1[@] array2[@]

并在函数中使用:

_array2["$index"]="$i"

第19行:   printf“ $ i \ n”          ^-SC2059:不要在printf格式字符串中使用变量。使用printf“ ..%s ..”“ $ foo”。

很好,但我也尝试了echo,同样的结果

1 个答案:

答案 0 :(得分:2)

我看到您的脚本有两个问题。第一个是在modify_array2函数内部,您使用了两个声明的局部变量,它们是由作为参数传递的值创建的。第二个是永远不要修改array2变量。

可能的解决方案是:

#!/bin/bash

array1=(1 2 3)
array2=()

modify_array2 () {
    #set array2 to be equal to array1 by iterating through array1's 
    #elements and setting the corresponding element by index of array2 by 
    #to be equal to the element in array1

    index=0
    local -n _array1=$1
    local -n _array2=$2
    for i in "${_array1[@]}"; do
        _array2["$index"]="$i"
        ((index++))
    done
}

printf "These are the contents of array1 before calling the function:\n"
printf "%s\n" "${array1[@]}"

printf "These are the contents of array2 before calling the function:\n"
printf "%s\n" "${array2[@]}"

modify_array2 array1 array2

printf "These are the contents of array2 after calling the function:\n"
printf "%s\n" "${array2[@]}"

我使用declare而不是local来创建两个局部变量。这只是我的个人喜好,因为declare使变量在函数中使用时就像在local中创建变量一样(请参阅help declare)。

但是与这个问题最相关的是处理传递给函数的参数的方式。在原始脚本中,它们是按值传递的。因此,不可能对参数列表中传递的第二个数组进行任何更改。

在提出的解决方案中,该函数称为传递数组本身(而不是其值)。在函数内部,将创建两个局部变量,作为对作为参数传递给函数的数组的引用。这就是-n选项的含义:为另一个变量创建一个 nameref (引用)。如果您在Bash手册页中查找 nameref ,您会看到“ shell函数中通常使用nameref来引用一个变量,该变量的名称作为参数传递给该函数”。这样,您对引用所做的任何赋值都将被视为对作为参数传递的变量的赋值。