- 首页
- 作品
- Bash 脚本教程
- Bash 数组
Bash 数组
数组(array)是一个包含多个值的变量。成员的编号从0开始,数量没有上限,也没有要求成员被连续索引。
创建数组
- 数组可以采用逐个赋值的方法创建。
ARRAY[INDEX]=value
- 上面语法中,
ARRAY
是数组的名字,可以是任意合法的变量名。INDEX
是一个大于或等于零的整数,也可以是算术表达式。注意数组第一个元素的下标是0, 而不是1。
- 下面创建一个三个成员的数组。
$ array[0]=val
$ array[1]=val
$ array[2]=val
- 数组也可以采用一次性赋值的方式创建。
ARRAY=(value1 value2 ... valueN)
# 等同于
ARRAY=(
value1
value2
value3
)
- 采用上面方式创建数组时,可以按照默认顺序赋值,也可以在每个值前面指定位置。
$ array=(a b c)
$ array=([2]=c [0]=a [1]=b)
$ days=(Sun Mon Tue Wed Thu Fri Sat)
$ days=([0]=Sun [1]=Mon [2]=Tue [3]=Wed [4]=Thu [5]=Fri [6]=Sat)
- 只为某些值指定位置,也是可以的。
names=(hatter [5]=duchess alice)
- 上面例子中,
hatter
是数组的0号位置,duchess
是5号位置,alice
是6号位置。
- 没有赋值的数组元素的默认值是空字符串。
- 定义数组的时候,可以使用通配符。
$ mp3s=( *.mp3 )
- 上面例子中,将当前目录的所有 MP3 文件,放进一个数组。
- 先用
declare -a
命令声明一个数组,也是可以的。
$ declare -a ARRAYNAME
read -a
命令则是将用户的命令行输入,存入一个数组。
$ read -a dice
- 上面命令将用户的命令行输入,存入数组
dice
。
读取数组
读取单个元素
读取所有成员
@
和*
是数组的特殊索引,表示返回数组的所有成员。
$ foo=(a b c d e f)
$ echo ${foo[@]}
a b c d e f
- 这两个特殊索引配合
for
循环,就可以用来遍历数组。
for i in "${names[@]}"; do
echo $i
done
@
和*
放不放在双引号之中,是有差别的。
$ activities=( swimming "water skiing" canoeing "white-water rafting" surfing )
$ for act in ${activities[@]}; \
do \
echo "Activity: $act"; \
done
Activity: swimming
Activity: water
Activity: skiing
Activity: canoeing
Activity: white-water
Activity: rafting
Activity: surfing
- 上面的例子中,数组
activities
实际包含5个成员,但是for...in
循环直接遍历${activities[@]}
,导致返回7个结果。为了避免这种情况,一般把${activities[@]}
放在双引号之中。
$ for act in "${activities[@]}"; \
do \
echo "Activity: $act"; \
done
Activity: swimming
Activity: water skiing
Activity: canoeing
Activity: white-water rafting
Activity: surfing
- 上面例子中,
${activities[@]}
放在双引号之中,遍历就会返回正确的结果。
${activities[*]}
不放在双引号之中,跟${activities[@]}
不放在双引号之中是一样的。
$ for act in ${activities[*]}; \
do \
echo "Activity: $act"; \
done
Activity: swimming
Activity: water
Activity: skiing
Activity: canoeing
Activity: white-water
Activity: rafting
Activity: surfing
${activities[*]}
放在双引号之中,所有成员就会变成单个字符串返回。
$ for act in "${activities[*]}"; \
do \
echo "Activity: $act"; \
done
Activity: swimming water skiing canoeing white-water rafting surfing
- 所以,拷贝一个数组的最方便方法,就是写成下面这样。
$ hobbies=( "${activities[@]}" )
- 上面例子中,数组
activities
被拷贝给了另一个数组hobbies
。
- 这种写法也可以用来为新数组添加成员。
$ hobbies=( "${activities[@]}" diving )
- 上面例子中,新数组
hobbies
在数组activities
的所有成员之后,又添加了一个成员。
默认位置
数组的长度
- 要想知道数组的长度(即一共包含多少成员),可以使用下面两种语法。
${#array[*]}
${#array[@]}
- 下面是一个例子。
$ a[100]=foo
$ echo ${#a[*]}
1
$ echo ${#a[@]}
1
- 上面例子中,把字符串赋值给
100
位置的数组元素,这时的数组只有一个元素。
- 注意,如果用这种语法去读取具体的数组成员,就会返回该成员的字符串长度。这一点必须小心。
$ a[100]=foo
$ echo ${#a[100]}
3
- 上面例子中,
${#a[100]}
实际上是返回数组第100号成员a[100]
的值(foo
)的字符串长度。
提取数组序号
提取数组成员
追加数组成员
删除数组
- 删除一个数组成员,使用
unset
命令。
$ foo=(a b c d e f)
$ echo ${foo[@]}
a b c d e f
$ unset foo[2]
$ echo ${foo[@]}
a b d e f
- 上面例子中,删除了数组中的第三个元素,下标为2。
- 将某个成员设为空值,可以从返回值中“隐藏”这个成员。
$ foo=(a b c d e f)
$ foo[1]=''
$ echo ${foo[@]}
a c d e f
- 上面例子中,将数组的第二个成员设为空字符串,数组的返回值中,这个成员就“隐藏”了。
- 注意,这里是“隐藏”,而不是删除,因为这个成员仍然存在,只是值变成了空值。
$ foo=(a b c d e f)
$ foo[1]=''
$ echo ${#foo[@]}
6
$ echo ${!foo[@]}
0 1 2 3 4 5
- 上面代码中,第二个成员设为空值后,数组仍然包含6个成员。
- 由于空值就是空字符串,所以下面这样写也有隐藏效果,但是不建议这种写法。
$ foo[1]=
- 上面的写法也相当于“隐藏”了数组的第二个成员。
- 直接将数组变量赋值为空字符串,相当于“隐藏”数组的第一个成员。
$ foo=(a b c d e f)
$ foo=''
$ echo ${foo[@]}
b c d e f
- 上面的写法相当于“隐藏”了数组的第一个成员。
unset ArrayName
可以清空整个数组。
$ unset ARRAY
$ echo ${ARRAY[*]}
<--no output-->
关联数组
下一节:set命令是 Bash 脚本的重要环节,却常常被忽视,导致脚本的安全性和可维护性出问题。本章介绍set的基本用法,帮助你写出更安全的 Bash 脚本。