shell中的数组
shell中的数组
数组是字符串列表,将整数映射成字符串。
创建数组
有几种方式创建数组:
-
使用=()语法
[root@k8s-node-4 ~]# names=("Bob" "Peter" "$USER" "Big Bad John") [root@k8s-node-4 ~]# echo ${names[0]} Bob [root@k8s-node-4 ~]# echo ${names[1]} Peter [root@k8s-node-4 ~]# echo ${names[2]} root [root@k8s-node-4 ~]# echo ${names[3]} Big Bad John数组的下标从0开始。
还可以手动为数组中的元素指定下标,这样创建的数组中有空洞"hole",被称为稀疏数组(sparse array)。
[root@k8s-node-4 ~]# names=([0]="Bob" [1]="Peter" [20]="$USER" [21]="Big Bad John") [root@k8s-node-4 ~]# echo ${names[0]} Bob [root@k8s-node-4 ~]# echo ${names[1]} Peter [root@k8s-node-4 ~]# echo ${names[20]} root [root@k8s-node-4 ~]# echo ${names[21]} Big Bad John -
使用命令的输出来构建数组
[root@k8s-node-4 ~]# IFS=. read -ra ip <<< "192.168.1.1" [root@k8s-node-4 ~]# echo ${ip[0]} 192 [root@k8s-node-4 ~]# echo ${ip[1]} 168 [root@k8s-node-4 ~]# echo ${ip[2]} 1 [root@k8s-node-4 ~]# echo ${ip[3]} 1可以使用操作符+=向数组中添加元素。被添加的元素也必须是数组。
下面的示例中,使用find命令查找文件,并使用NUL字符分割文件名,并动态地向数组中添加元素。
[root@k8s-node-4 sh_learn]# ll total 4 -rw-r--r-- 1 root root 35 Sep 1 11:36 abc.log -rw-r--r-- 1 root root 0 Sep 1 09:43 music~1.mp3 -rw-r--r-- 1 root root 0 Sep 1 09:43 music~2.mp3 -rw-r--r-- 1 root root 0 Sep 1 09:43 music~3.mp3 -rw-r--r-- 1 root root 0 Sep 1 09:53 os-1.log -rw-r--r-- 1 root root 0 Sep 1 09:53 os-2.log -rw-r--r-- 1 root root 0 Sep 1 09:53 os-3.log [root@k8s-node-4 sh_learn]# files=() [root@k8s-node-4 sh_learn]# while read -r -d ''; do files+=("$REPLY"); done < <(find . -maxdepth 1 -type f -print0) [root@k8s-node-4 sh_learn]# for f in ${files[@]}; do echo $f; done ./music~1.mp3 ./music~2.mp3 ./music~3.mp3 ./os-1.log ./os-2.log ./os-3.log ./abc.log
使用数组
假设变量my_array是一个数组。可以使用语法"${my_array[@]}"将数组展开成字符串列表,数组中的每个元素都是一个单独的字符串。然后可以使用for语句进行遍历。
[root@k8s-node-4 sh_learn]# declare -p files
declare -a files=([0]="./os-1.log" [1]="./os-2.log" [2]="./os-3.log" [3]="./abc.log" [4]="./let her go.mp3" [5]="./you're beautiful.mp3" [6]="./Someone like you.mp3")
#注意,下面的命令中,必须使用双引号将${files[@]}括起来
[root@k8s-node-4 sh_learn]# for f in "${files[@]}"; do echo $f; done
./os-1.log
./os-2.log
./os-3.log
./abc.log
./let her go.mp3
./you're beautiful.mp3
./Someone like you.mp3
#如果没有双引号,则会导致错误的单词分割
[root@k8s-node-4 sh_learn]# for f in ${files[@]}; do echo $f; done
./os-1.log
./os-2.log
./os-3.log
./abc.log
./let
her
go.mp3
./you're
beautiful.mp3
./Someone
like
you.mp3
还可以使用下标来引用数组中的指定元素。
[root@k8s-node-4 sh_learn]# names=("Alice" "Bob" "Cindy")
[root@k8s-node-4 sh_learn]# echo ${names[0]}
Alice
[root@k8s-node-4 sh_learn]# echo ${names[1]}
Bob
[root@k8s-node-4 sh_learn]# echo ${names[2]}
Cindy
下标引用时,[]内可以是算术表达式,例如,下列示例遍历数组,每次处理2个元素:
注意:针对普通数组,在[]内,可以不使用$
[root@k8s-node-4 sh_learn]# a=(a b c q w x y z)
[root@k8s-node-4 sh_learn]# for ((i=0; i < ${#a[@]}; i+=2)); do echo "${a[i]}"*"${a[i+1]}"; done
a*b
c*q
w*x
y*z
使用语法"${arrayname[*]}",将数组中的所有元素组合成单个字符串。
[root@k8s-node-4 sh_learn]# names=("Alice" "Bob" "Cindy")
[root@k8s-node-4 sh_learn]# echo ${names[*]}
Alice Bob Cindy
还可以使用IFS来指定合并后字符串中数组元素之间的分隔符:
注意:需要使用双引号将${arrayname[*]}括起来,否则IFS的值不会生效。
[root@k8s-node-4 sh_learn]# names=("Alice" "Bob" "Cindy")
[root@k8s-node-4 sh_learn]# IFS=,; echo "${names[*]}"
Alice,Bob,Cindy
#没有双引号时,IFS的值不生效
[root@k8s-node-4 sh_learn]# IFS=,; echo ${names[*]}
Alice Bob Cindy
可以使用语法${#array[@]}来获取数组中元素的个数:
[root@k8s-node-4 sh_learn]# names=([1]="Alice" [11]="Bob" [21]="Clack" [31]="Duke")
[root@k8s-node-4 sh_learn]# echo ${#names[@]}
4
使用语法 "${!arrayname[@]}"来获取数组中的下标列表:
[root@k8s-node-4 sh_learn]# names=([1]="Alice" [11]="Bob" [21]="Clack" [31]="Duke")
[root@k8s-node-4 sh_learn]# echo ${!names[@]}
1 11 21 31
稀疏数组
稀疏数组是指下标不连续的数组。即数组中包含空洞(holes)。
有多重方式创建稀疏数组。
-
在创建数组时,直接为元素指定下标。
[root@k8s-node-4 ~]# names=([0]="Bob" [1]="Peter" [20]="$USER" [21]="Big Bad John") [root@k8s-node-4 ~]# echo ${names[0]} Bob [root@k8s-node-4 ~]# echo ${names[1]} Peter [root@k8s-node-4 ~]# echo ${names[20]} root [root@k8s-node-4 ~]# echo ${names[21]} Big Bad John -
在数组创建好之后,跳过结尾的下标为数组赋值。
[root@k8s-node-4 sh_learn]# chars=(a b c d) [root@k8s-node-4 sh_learn]# chars[10]=j [root@k8s-node-4 sh_learn]# declare -p chars declare -a chars=([0]="a" [1]="b" [2]="c" [3]="d" [10]="j") -
在数组创建好之后,使用unset来删除中间元素。
[root@k8s-node-4 ~]# declare -p numbers declare -a numbers=([0]="1" [1]="2" [2]="3" [3]="4") [root@k8s-node-4 ~]# unset ‘numbers[2]’ [root@k8s-node-4 ~]# declare -p numbers declare -a numbers=([0]="1" [1]="2" [3]="4")unset可以被用来删除数组中的任意元素。
注意:使用unset时,数组元素要使用单引号括起来,以避免shell将其解释为文件名展开。
#当前目录下有一个文件名称为numbers3 [root@k8s-node-4 number]# ll total 0 -rw-r--r-- 1 root root 0 Sep 2 14:04 numbers3 #定义了一个数组变量numbers [root@k8s-node-4 number]# declare -p numbers declare -a numbers=([0]="1" [1]="2" [2]="3" [3]="4") #尝试unset数组中序号为3的元素 [root@k8s-node-4 number]# unset numbers[3] #由于未使用单引号将numbers[3]括起来,它被展开为当前目录下的文件numbers3,导致unset失败 [root@k8s-node-4 number]# declare -p numbers declare -a numbers=([0]="1" [1]="2" [2]="3" [3]="4") #使用正确的unset方式 [root@k8s-node-4 number]# unset 'numbers[3]' [root@k8s-node-4 number]# declare -p numbers declare -a numbers=([0]="1" [1]="2" [2]="3")
可以使用下面的方法为稀疏数组重新生成连续的下标。
#创建稀疏数组,下标不连续
[root@k8s-node-4 number]# names=([1]="Alice" [11]="Bob" [21]="Clack" [31]="Duke")
[root@k8s-node-4 number]# echo "${!names[@]}"
0 1 11 21 31
#使用连续的下标重建数组
[root@k8s-node-4 number]# names=("${names[@]}")
[root@k8s-node-4 number]# echo "${!names[@]}"
0 1 2 3 4
关联数组(Associative Array)
关联数组类似于其它编程语言中的字典。它将一个字符串映射成另一个字符串。
使用declare -A来定义关联数组。
[root@k8s-node-4 number]# declare -A nations=(["US"]="United States" ["UK"]="United Kingdom")
[root@k8s-node-4 number]# echo "${nations["UK"]}"
United Kingdom
需要注意两点:
- 当使用
"${!array[@]}"来获取关联数组的键列表时,返回的列表内容的顺序是不确定的。同样,当使用"${array[@]}"来获取关联数组的值列表时,返回的列表内容的顺序也是去确定的。所以,关联数组不适合被用来存储需要按特定顺序处理的数据。 - 在使用[]来引用单个元素时,若在[]中使用变量,则不能省略$。

浙公网安备 33010602011771号