6.7 数组
Bash提供了一维索引数组和关联数组变量。任何变量都可用作索引数组,内建命令 declare 用于明确地声明一个数组。一个数组既没有大小上的上限,也没有要求成员必须连续索引或者赋值。索引数组使用整数引用(包括算术表达式,参见 shell算术 章节),并且从0开始。关联数组使用明确的字符串引用。除非特别说明,索引数组的索引必须是非负整数。
如果任何变量使用如下语法赋值,则会自动地创建一个索引数组,
name[subscript]=value
subscript 按算术表达式对待,必须计算出一个数字。如果 subscript 计算的结果小于0,则等于从数组最大索引+1开始的偏移,(即,-1 指向数组的最后一个元素)。明确地声明一个数组,要这样,
declare -a name
这样也行,
declare -a name[subscript]
subscript 可以忽略。
这样创建关联数组,
declare -A name
可以使用内建命令 declare 和 readonly 指定数组变量的属性。每个属性应用于数组的所有成员。
给数组赋值,可以使用组合赋值的形式,
name=(value1 value2 …)
其中,每一个 value 的形式是 [subscript]=string 。索引数组不需要括号和 subscript 。在给索引数组赋值时,如果提供了可选的 subscript ,则把它赋值给索引,被赋值的元素的索引是上一个索引+1。索引从0开始。
给关联数组赋值时,subscript 是必须的。
内建命令 declare 也接受此语法。可以使用上面介绍的 name[subscript]=value 给单个数组元素赋值。
数组的元素使用 ${name[subscript]} 引用。大括号是必须的,以避免和shell 的文件名扩展操作符冲突。如果 subscript 是 ‘@’ 或 ‘*’ ,则扩展为数组 name 的所有成员。区别仅仅是,在这两个字符出现在双引号中。如果在双引号中,则 ${name[*]} 扩展成一个单独的字,它的值是由IFS变量的第一个字符分隔的每个数组成员,而 ${name[@]} 扩展为,数组 name 的每个元素都是独立的字。当数组没有成员时, ${name[@]} 扩展为 nothing。 如果一个字中间出现双引号扩展,则第一个参数的扩展,连接着原始字的开头部分,最后的参数的扩展,连接到原始字的最后的那部分。类似于特别参数 ‘@’ 和 ‘*’的扩展。 ${#name[subscript]} 扩展到 ${name[subscript]} 的长度。如果 subscript 是 ‘@’ 或 ‘*’ ,扩展是数组中的元素个数。引用一个数组变量时,没有指定 subscript ,相当于使用 subscript = 0 引用。 如果 subscript 计算的结果小于0,则等于从数组最大索引+1开始的偏移,就是说,负值的索引是从数组末尾开始向回数的,-1 指向数组的最后一个元素。
如果 subscript 被赋值了,则一个数组变量被认为是已设置了。 null 字符串是有效值。
可以像获取数组元素一样,来获取数组的索引, ${!name[@]} 和 ${!name[*]}扩展为数组变量name的索引。当它被双引号包围时,和上述对特殊参数 ‘@’ 或 ‘*’的处理类似。
内建命令 unset 用来销毁数组。 unset name[subscript] 销毁位于 subscript 的数组元素。负值的subscript按照上述负值索引处理。请注意,避免由于文件名扩展引起的预料外的副作用。 unset name, name是数组的话,整个数组被销毁。如果 subscript 是 ‘@’ 或 ‘*’ , 也销毁整个数组。
内建命令 declare, local, 和 readonly 都接受 -a 选项,以指定一个索引数组, -A 选项以指定一个关联数组。如果两个选项同时出现,则 -A 优先。内建命令 read 接受 -a 选项以接受从标准输入读入字列表到一个数组中,也可以从标准输入读取值到单个的数组元素中。 内建命令 set 和 declare ,以能够重用为输入的格式,显示数组值。