一、索引数组
shell中的索引数组,可通过declare -a xxx
显式声明(shell中declare
用来声明一个变量类型,-a
参数表示声明后面的变量为数组类型),也可以不声明直接对一个变量应用数组相关的操作变为数组,比如arr[3]=1
这种方式直接赋值,shell也会将arr当作一个数组看待。
声明只是增加代码可读性,对代码逻辑无影响。即使声明为数组类型,依然可以作为单变量赋值。
索引数组在arr=(value1 value2 value3 ...)
的方式初始化时,默认的索引下标index
是0起始的整数,0,1,2,…。
对索引数组的赋值arr[index]=value
,相同index
赋值时会覆盖,且index
不强制要求连续,可间断赋值。间断赋值时${#arr[@]}
或${#arr[*]}
求数组长度时仅会统计实际存在的索引数量,被间断的索引不会参与统计。
shell数组中的特点:支持稀疏索引。
删除某个位置索引可以通过unset arr[index]
,删除后该位置索引不会参与数组长度的统计。
比如执行下面这段代码的输出:
#!/bin/bash
arr=(1 2 3)
arr[5]=4
arr['7']=5
echo "获取数组的值: ${arr[*]}"
echo "获取数组的值: ${arr[@]}"
echo "获取数组长度: ${#arr[*]}"
echo "获取数组长度: ${#arr[@]}"
echo "获取数组的键: ${!arr[*]}"
echo "获取数组的键: ${!arr[@]}"
echo "删除位置1的索引元素: ---------"
unset arr[1]
echo "获取数组的值: ${arr[*]}"
echo "获取数组的值: ${arr[@]}"
echo "获取数组长度: ${#arr[*]}"
echo "获取数组长度: ${#arr[@]}"
echo "获取数组的键: ${!arr[*]}"
echo "获取数组的键: ${!arr[@]}"
# 获取数组的值: 1 2 3 4 5
# 获取数组的值: 1 2 3 4 5
# 获取数组长度: 5
# 获取数组长度: 5
# 获取数组的键: 0 1 2 5 7
# 获取数组的键: 0 1 2 5 7
# 删除位置1的索引元素: ---------
# 获取数组的值: 1 3 4 5
# 获取数组的值: 1 3 4 5
# 获取数组长度: 4
# 获取数组长度: 4
# 获取数组的键: 0 2 5 7
# 获取数组的键: 0 2 5 7
索引数组的下标只会是整数,尽管shell中默认将所有字符当作字符串,但在arr[index]=value
形式赋值时shell会自动将字符解释为整数(index
必须是可解释为整数类型的字符串)。
!在索引数组中使用字符串当做键尽管不会报错,但可能会导致数组运算上的一些逻辑的错误。
二、关联数组
shell中的关联数组在bash4及以上才开始支持。查看bash版本bash --version
。
shell中的关联数组类似于python中的字典,允许键为字符串类型。使用前必须通过declare -A xxx
声明。
关联数组的增删改查操作都和上面索引数组类似,同名索引也会相互覆盖,不多余说明了,唯一需要注意的是,无论关联数组的键可否被解释为整数类型,都会当做字符串类型看待。且关联数组不支持0起始的整数型下标索引。
#!/bin/bash
declare -A arr
arr=([a]=1 [b]=2 [c]=3)
arr[1]=4
echo "获取数组的值: ${arr[*]}"
echo "获取数组的值: ${arr[@]}"
echo "获取数组长度: ${#arr[*]}"
echo "获取数组长度: ${#arr[@]}"
echo "获取数组的键: ${!arr[*]}"
echo "获取数组的键: ${!arr[@]}"
echo "删除键为'1'的索引元素: ---------"
unset arr[1]
echo "获取数组的值: ${arr[*]}"
echo "获取数组的值: ${arr[@]}"
echo "获取数组长度: ${#arr[*]}"
echo "获取数组长度: ${#arr[@]}"
echo "获取数组的键: ${!arr[*]}"
echo "获取数组的键: ${!arr[@]}"
# 获取数组的值: 1 2 3 4
# 获取数组的值: 1 2 3 4
# 获取数组长度: 4
# 获取数组长度: 4
# 获取数组的键: a b c 1
# 获取数组的键: a b c 1
# 删除键为'1'的索引元素: ---------
# 获取数组的值: 1 2 3
# 获取数组的值: 1 2 3
# 获取数组长度: 3
# 获取数组长度: 3
# 获取数组的键: a b c
# 获取数组的键: a b c
tips!
1.数组赋值时是否使用引号的区别
不带引号赋值,会将所有输入元素按照空格分隔。
带引号赋值,可以将引号中的内容识别为一个整体,即使引号中的元素包含空格。
至于单双引号的区别,在于是否需要变量或命令替换。
#!/bin/bash
arr1=(a b c d)
arr2=("a b" "c d")
for item in "${arr1[@]}"; do
echo $item
done
echo "-----"
for item in "${arr2[@]}"; do
echo $item
done
# a
# b
# c
# d
# -----
# a b
# c d
2.数组读取时是否使用引号的区别
和2类似,不加:无论数组中的元素在赋值时是何种形式,在读取时默认都按照空格拆分为多个独立元素。
加:会保持赋值时元素个数的独立性。
#!/bin/bash
arr=("a b" "c d")
for item in ${arr[@]}; do
echo $item
done
echo "-----"
for item in "${arr[@]}"; do
echo $item
done
# a
# b
# c
# d
# -----
# a b
# c d
3.*
和@
的使用区别
主要分为数组长度统计和遍历两个场景。
在${#arr[*]}
或${#arr[@]}
获取数组长度时无区别,且无论加不加引号,获取的都是数组的实际长度,但推荐后者,更符合习惯。
#!/bin/bash
arr=("a b" "c d")
echo ${#arr[*]}
echo ${#arr[@]}
echo "${#arr[*]}"
echo "${#arr[@]}"
# 2
# 2
# 2
# 2
在遍历数组时,主要区别在于读取数组时是否加双引号。
- 不加引号:无区别,不保证元素的独立性,都是按照空格分隔为多个元素遍历输出。元素中如果包含空格也会被拆分输出。
- 加引号:
@
会保持数组中元素的独立性,实际有几个输出几次,元素可以包含空格不被拆分;*
会将数组中所有元素按照空格拼接为一个字符串输出。
#!/bin/bash
arr=("a b" "c d")
for item in ${arr[*]}; do
echo $item
done
echo "-----"
for item in ${arr[@]}; do
echo $item
done
echo "-----"
for item in "${arr[*]}"; do
echo $item
done
echo "-----"
for item in "${arr[@]}"; do
echo $item
done
# a
# b
# c
# d
# -----
# a
# b
# c
# d
# -----
# a b c d
# -----
# a b
# c d
4.获取数组的键索引
shell中数组默认获取输出数组的值,获取数组的键可以通过${!arr[*]}
或${!arr[@]}
,二者的使用区别同上面3。
索引数组:
#!/bin/bash
declare -A arr
arr['a c']=1
arr['b']=2
for item in ${!arr[*]}; do
echo $item
done
echo "-----"
for item in ${!arr[@]}; do
echo $item
done
echo "-----"
for item in "${!arr[*]}"; do
echo $item
done
echo "-----"
for item in "${!arr[@]}"; do
echo $item
done
# a
# c
# b
# -----
# a
# c
# b
# -----
# a c b
# -----
# a c
# b
关联数组:
#!/bin/bash
arr=(a b c)
for item in ${!arr[*]}; do
echo $item
done
echo "-----"
for item in ${!arr[@]}; do
echo $item
done
echo "-----"
for item in "${!arr[*]}"; do
echo $item
done
echo "-----"
for item in "${!arr[@]}"; do
echo $item
done
# 0
# 1
# 2
# -----
# 0
# 1
# 2
# -----
# 0 1 2
# -----
# 0
# 1
# 2