在bash shell 函数传递数组的问题
最近 写shell 脚本中,遇到一个 往函数里面 传递数组作为参数的问题, 特此来记录一下。
在函数中如何 传递 传递数组变量 ?
bash
# !/bin/bash
# array variable to function test
#
function testit {
# 定义变量
local newarray
# 重新构建一个新的数组
newarray=(`echo "$@"`)
echo "The new array value is: ${newarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is ${myarray[*]}"
# 注意这里传递方式 是把整个数组进行传递
testit ${myarray[*]}
这种方式 就是把整个数组 全部传入, 在函数内部重新构建 这个数组。 缺点也很明显,如果我需要传递两个数组呢? 如果想传递两个变量,有数组和其他的变量呢?
上面的例子会有潜在的问题,如果数组元素 本身是有空格的,这样在重建数组的时候 会有问题,来看下面的例子:
bash
# !/bin/bash
# array variable to function test
#
function testit {
# 定义变量
local newarray
# 重新构建一个新的数组
newarray=($(echo "$@"))
# newarray=("$@")
# echo "The new array value is: ${newarray[*]}"
for value in "${newarray[@]}"; do
echo "array item: $value"
done
echo "数组长度为: ${#newarray[@]}"
}
myarray=("文件 1" "文件 2" "文件 3")
echo "The original array is ${myarray[*]}"
# 注意这里传递方式 是把整个数组进行传递
# testit ${myarray[*]}
testit "${myarray[@]}"
上面代码运行结果如下:
reStructuredText
sh local_test.sh
The original array is 文件 1 文件 2 文件 3
array item: 文件
array item: 1
array item: 文件
array item: 2
array item: 文件
array item: 3
数组长度为: 6
我们发现数组项被拆分了, 文件 , 1 ,文件, 2 ,文件,3
这显然不是我们希望的样子。
这个问题的关键 就是newarray 生成的时候 默认是空格作为划分的。 echo 默认是以空格作为划分的。
bash
function testit {
# 定义变量
local newarray
# 重新构建一个新的数组
# 错误写法
# newarray=($(echo "$@"))
# 直接使用 "$@" 来构建数组即可
newarray=("$@")
# echo "The new array value is: ${newarray[*]}"
for value in "${newarray[@]}"; do
echo "array item: $value"
done
echo "数组长度为: ${#newarray[@]}"
}
myarray=("文件 1" "文件 2" "文件 3")
testit "${myarray[@]}"
结果如下:
reStructuredText
sh local_test.sh
array item: 文件 1
array item: 文件 2
array item: 文件 3
数组长度为: 3
此时的结果就是对的, 数组的元素 没有被拆分,并且数组的长度是3 ,没有问题。
这里要注意几点:
第一点: 在调用 testit 函数的时候 需要传递 "${myarray[@]}"
而不要传递 "${myarray[*]}"
这两个参数 是有一点区别的。
第二点 构建数组的时候: newarray=("$@")
使用这种方式, 不要使用echo 进行打印。
"${myarray[@]}"
vs. "${myarray[*]}"
这两个的区别 ?
表达式 | 含义 | 特点说明 |
---|---|---|
"${myarray[@]}" |
把数组每个元素作为独立的参数传递 | 推荐使用 |
"${myarray[*]}" |
把整个数组当作一个字符串,用 IFS 拼接 | 容易出错 |
看个例子 :
bash
myarray=("apple" "banana cherry" "date")
for item in "${myarray[@]}"; do
echo "Item: '$item'"
done
echo "----------{myarray[*]}-------------"
for item in "${myarray[*]}"; do
echo "Item: '$item'"
done
运行结果:
reStructuredText
sh local_test.sh
Item: 'apple'
Item: 'banana cherry'
Item: 'date'
----------{myarray[*]}-------------
Item: 'apple banana cherry date'
"${myarray[*]}"
会把整个数组的元素当成一个字符串进行传递。
"${myarray[@]}"
这种方式 就不会出现 这个问题,把数组的每一项单独 传递。
场景 | 推荐写法 | 原因 |
---|---|---|
遍历数组元素 | "${myarray[@]}" |
正确处理带空格的元素 |
获取所有元素拼接成字符串 | "${myarray[*]}" |
明确需要字符串拼接时才使用 |
传递多个参数给函数/命令 | "${myarray[@]}" |
每个元素作为一个独立参数 |
当然 如果你的 bash shell 的版本 比较高,version 大于等于5.0 ,那么可以有更好的传递方式,使用 nameref
这种特性,来方便的传递数组,等有时间我在进行补充说明吧。
分享快乐,留住感动. '2025-07-07 22:32:52' --frank