Bash-使用函数修改数组
我不明白为什么这个示例脚本没有修改array2的内容。似乎我们应该能够通过迭代array1的元素并通过array2的索引将相应的元素设置为等于array1中的元素,从而将array2设置为等于array1Bash-使用函数修改数组,bash,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 th
#!/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行:
数组1=(1 2 3)
^--SC2034:阵列1似乎未使用。验证是否使用(如果外部使用,则导出)。
没有意义,我显然是在用它:
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,同样的结果我发现您的脚本有两个问题。第一个是在
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[@]}"
我使用local
来创建两个局部变量,而不是declare
。这只是我个人的喜好,因为declare
使变量在函数中使用时成为局部变量,就好像它们是使用local
创建的一样(请参见帮助declare
)
但与问题更相关的是处理传递给函数的参数的方式。在原始脚本中,它们是按值传递的。因此,不可能对参数列表中传递的第二个数组进行任何更改
在建议的解决方案中,调用函数传递数组本身(而不是数组值)。在函数内部,创建两个局部变量作为对作为参数传递给函数的数组的引用。这就是
-n
选项的含义:创建另一个变量的nameref(引用)。如果在Bash手册页中查找nameref,您将看到“nameref通常在shell函数中用于引用其名称作为参数传递给函数的变量”。这样,您对引用所做的任何赋值都被视为对作为参数传递的变量的赋值。我发现您的脚本存在两个问题。第一个是在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[@]}"
我使用local
来创建两个局部变量,而不是declare
。这只是我个人的喜好,因为declare
使变量在函数中使用时成为局部变量,就好像它们是使用local
创建的一样(请参见帮助declare
)
但与问题更相关的是处理传递给函数的参数的方式。在原始脚本中,它们是按值传递的。因此,不可能对参数列表中传递的第二个数组进行任何更改
在建议的解决方案中,调用函数传递数组本身(而不是数组值)。在函数内部,创建两个局部变量作为对作为参数传递给函数的数组的引用。这就是
-n
选项的含义:创建另一个变量的nameref(引用)。如果在Bash手册页中查找nameref,您将看到“nameref通常在shell函数中用于引用其名称作为参数传递给函数的变量”。这样,您对引用所做的任何赋值都将被视为对作为参数传递的变量的赋值。添加一个shebang,然后将脚本粘贴到此处:添加此,感谢添加一个shebang,然后将脚本粘贴到此处:添加此,感谢从手册中引用关于将变量声明为nameref
的内容,这可能会使这个答案更好。谢谢,这似乎是可行的。我试图从在线文档中找到local-n的用法,因为我以前见过它,但令人惊讶的是,它似乎没有很好的文档记录。我知道传递数组的值可能是一个问题,但我还不明白本地与全局作用域是一个问题。@Fingers:seehelp local
@oguzismail我添加了一个额外的段落,其中提到了Bash手册页中包含的nameref定义。@Fingers我编辑了对建议的解决方案澄清了您可以使用local
或declare
,因为declare
在函数中使用时创建变量,就像它们是由local
创建的一样。添加手册中关于将变量声明为nameref
的引文可能会更好地回答这个问题,这似乎奏效了。我试图从在线文档中找到local-n的用法,因为我以前见过它,但令人惊讶的是,它似乎没有很好的文档记录。我知道传递数组的值可能是一个问题,但我还不明白本地与全局作用域是一个问题。@Fingers:seehelp local
@oguzismail我添加了一个额外的段落,其中提到了Bash手册页中包含的nameref定义。@Fingers我编辑了对建议的解决方案澄清了您可以使用local
或declare
,因为declare
在函数中使用时创建变量,就像它们是由local
创建的一样。