1 分钟阅读

Bash 支持一维数组的语法,可以把一组字符串组成数组,通过一个数组名实现对一组值的操作。

创建数组

a) 把一个数组常量赋值给变量时,变量就会自动被声明为数组:

arr=(element0 element1 element2 )

b) 在数组常量内指定下标,可以实现对特定位置的元素进行赋值:

# arr[0],arr[3] 为空
arr=([1]=element1 element2 [4]=element3)

c) 直接对数组元素赋值,也会创建一个新的数组。

arr[0]=element0

以上 3 种直接对数组或数组元素赋值,都会自动创建对应的数组变量。

d) 如果想声明一个数组变量,但不初始化,可以使用

# 不支持直接初始化
declare -a arr

获取数组元素

数组元素 arr[i] 的使用和普通变量基本相同:

# 大括号{}不能省略
# 获取元素
${arr[i]}

# 赋值
arr[i]=value

数组的长度

变量展开 ${#arr[@]} 的结果为数组的长度。

💡 ${#arr[*]} 也表示数组长度。

看个问题:

arr=(0 1 [4]=4)
echo ${#arr[@]}  # 3

这说明, arr 的结构是 ([0]=0 [1]=1 [4]=4),而不是 (0 1 null null 4),所以,数组的内部结构更像是 map。Bash 并没有要求下标是连续的。

数组遍历

${arr[@]}${arr[*]} 展开为数组的全部元素。

二者的区别与 $@$* 类似,在执行单词分割的上下文中,前者可被分割为单个元素,后者作为整体不可分割。

pets=("a cat" "a dog")

# 这是理想的遍历效果
for pet in "${pets[@]}"; do echo $pet; done
# a cat
# a dog

# "${arr[*]}" 把所有元素拼在一起
for pet in "${pets[*]}"; do echo $pet; done
# a cat a dog

# 不加引号,会以空格分割
for pet in ${pets[@]}; do echo $pet; done
# a
# cat
# a
# dog

💡 使用 arr[@] 的地方都可以使用 arr[*] 它们的区别与上例类似,下面忽略 arr[*] 写法。

如果要通过下标遍历,需要使用 "${!name[@]}"

for i in "${!arr[@]}"; do echo "arr[${i}]=${arr[i]}"; done
# arr[0]=0
# arr[1]=1
# arr[4]=4

因为数组的下标并不一定是连续递增,通过 0…len 的下标遍历长度为 len 的数组并不靠谱。

数组切片

数组切片与字符串子串语法类似。

${arr[@]:offset:len}

表示从 arr[offset] 开始,长度为 len 的数组。

其中,offset 可以为负数。len 非负, 省略时表示直到数组末尾。

arr=(0 1 2 3 4 a b c d)

echo ${arr[4]}
# 4 a b c d

echo ${arr[@]:4:2}
# 4 a

# offset 为负时,注意前面需要加空格
echo ${arr[@]: -4: 2}
# a b

数组元素的增删

往数组最后增加其它元素(push),可以使用

arr+=(value1 value2 ...)

灵活使用切片和赋值,可以实现多种数组操作。

# push
arr=("${arr[@]}" value1 value2 )

# shift
arr=(value1 value2 "${arr[@]}")

# insert(在下标从0开始且连续的前提下)
arr=("${arr[@]:0:2}" value1 value2 "${arr[@]:2}")

# remove(在下标从0开始且连续的前提下)
arr=("${arr[@]:0:2}" "${arr[@]:3}")

删除数组

与删除普通变量类似,使用 unset 命令删除数组元素或者整个数组变量:

# 删除数组
unset arr

# 删除arr数组中下标为2的值。
unset arr[2]

特殊的数组:关联数组

Bash 还支持一种更通用的数组语法 —— 关联数组(associative array),可以在数组中使用字符串作为下标。普通数组是数字到字符串的映射,关联数组建立了字符串到字符串的映射,是更通用的 map 结构。

ass_arr=(["white"]="#fff" ["green"]="#0f0") # 或者使用 declare -A 声明
echo ${ass_arr["white"]} # #fff

参考

留下评论