Bash 数组
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
留下评论