注意事项
并不是每种 Shell 都支持数组(比如 Bash 支持数组,但是 Dash 不支持数组),为了写出可移植脚本,不建议使用数组。
The Bourne shell or the Unix sh lanuage specification don't support arrays.
定义 - 如何定义一个数组?
索引数组
# 声明索引数组 declare -a mIndexArray # 索引数组也可以直接定义: mIndexArray=(one two three)
关联数组
# 声明关联数组 declare -A mAssociativeArray # 但是,关联数组不可以直接定义,必须先声明: declare -A mAssociativeArray mAssociativeArray=( [foo]=bar [baz]=quux [corge]=grault ) # 如果没有先声明为关联数组,则 mAssociativeArray=( [foo]=bar [baz]=quux [corge]=grault ) 默认为索引数组,并且其中的元素也发生了变化。
赋值 - 如何对数组进行赋值?
对索引数组和关联数组进行赋值方面,两者直接并无太大差异:
# mAssociativeArray[five]=five
数组索引也可以是变量:
即使索引是“存在空格的字符串”,也不需要引用:
# mAssociativeArray["key with space"]=value
# mAssociativeArray[key with space]=value
上面的三个是等价的。
也可以使用如下方式,以无需索引的方式向数组中添加元素:
# mIndexArray+=('foo')
# mIndexArray+=('bar')
上面的示例向索引数组mIndexArray中添加了两个元素,但是无需指定索引。
取值 - 如何取值及打印整个数组?
从数组中取值
对索引数组和关联数组进行取值方面,两者直接并无太大差异:
# echo ${mAssociativeArray[five]}
# echo ${mArray[$var]}
# ehco ${mArray[var with space]}
如上示例。
打印整个数组
打印整个数组的方式有些特殊。下面的这个做法是错误的:
# echo $mAssociativeArray
对于上面的示例,索引数组只会打印第一个元素,而关联数组则输出空。
打印数组中元素的正确形式应该是:
# echo ${mAssociativeArray[*]}
# echo ${mAssociativeArray[@]}
上述的两种形式并无差异,但打印的都是数组中值,并不包含索引。
如果要打印索引,则应该:
# echo ${!mAssociativeArray[*]}
# echo ${!mAssociativeArray[@]}
上述示例将打印数组的所有索引。
使用循环打印整个数组
上面的示例已经能够获取数组的索引和值了,所以循环也不会很麻烦:
do
echo ${mAssociativeArray[$key]}
do
do
上述示例分别演示了打印数组索引和值的方法。
如何判断某个索引是否存在?
使用常用的if语句即可:
如果找到了索引,则打印“Fount”字符串。
删除 - 如何删除数组及其中某个元素?
删除数组
如果要删除一个关联数组或者索引数组,可以进行unset操作:
# unset mIndexArray
注意事项:重新声明(declare)并不能删除覆盖原有的数组;指定要删除的数组时,没有美元($)符号;
删除元素
删除元素只需要指定数组中元素即可:
# unset mIndexArray[0]
注意事项:指定要删除的数组元素时,没有美元($)符号;索引数组中元素的索引也不会前移(例如,删除索引为3的元素,那索引为4的元素的索引不会变为3)。
删除元素时,如果索引中包含空格
如果删除元素的索引包含空格则需要进行引用,这里比较特殊:
# unset mAssociativeArray["$var"]
这里比较特殊的。与取值、赋值时“即使存在空格也无需引用”的情形有些不同。
长度 - 如何获取数组的长度?
使用井号(#)来获取数组的长度,形式如下:
# echo ${#mAssociativeArray[*]}
# echo ${#mAssociativeArray[@]}
这种用法也可以用于计算字符串的长度。
传参 - 如何将数组作为函数参数传递?
这一点就比较奇怪了,如果要讲数组传递到函数里,有两个办法:
或者,将数组的值全部传递到函数中,然后在函数组使用$@取到所有值,然后放在函数中的一个数组中。
目前,我还没有找到直接传递数组的方法。 参考「How to pass an array as function argument?」一文。
拼接 - 拼接数组元素
特殊场景:我们可以换个思路,使用 seq 命令,生成有规律的数据:
# seq -s ', ' -f '192.168.1.%.0f:2000' 10 15 192.168.1.10:2000, 192.168.1.11:2000, 192.168.1.12:2000, 192.168.1.13:2000, 192.168.1.14:2000, 192.168.1.15:2000
注意事项
奇怪的作用域
函数隐式创建的数组,将作用与全局:
function createWithoutDeclare() {
createWithoutDeclare
echo ${mAssociativeArray[foo]}
函数显式创建的数组,将作用于本地:
function createWithDeclare() {
createWithDeclare
echo ${mAssociativeArray[foo]}
这一特性是declare导致的,也不足为奇怪,可以参考declare的说明(执行help decalre命令来查看,因为declare是Bash的内建命令)。
在 Dash 中,使用数组
#!/bin/sh
var="this is a test|second test|the quick brown fox jumped over the lazy dog"
oldIFS=$IFS
IFS="|"
set -- $var
echo "$1"
echo "$2"
echo "$3" # Note: if more than $9 you need curly braces e.g. "${10}"
IFS=$oldIFS
参考文献
WikiNotes/数组的使用
Add a new element to an array without specifying the index in Bash
How to pass an array as function argument?
Bash associative array examples
Does `dash` support `bash` style arrays?
Looping over arrays, printing both index and value
Arrays in Unix Bourne Shell - Unix & Linux Stack Exchange
本文详细介绍了Bash shell中数组的定义、赋值、取值、删除、长度计算、传递以及特殊作用域等操作,并对比了不支持数组的Dash。还提到了在数组操作中关于空格处理的注意事项,以及如何在特定场景下利用seq命令生成数据。最后,文章揭示了在函数中使用数组的奇怪作用域现象,并提供了在Dash中处理类似问题的方法。
2021

被折叠的 条评论
为什么被折叠?



