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

需要注意两点:

  1. 当使用 "${!array[@]}" 来获取关联数组的键列表时,返回的列表内容的顺序是不确定的。同样,当使用"${array[@]}"来获取关联数组的值列表时,返回的列表内容的顺序也是去确定的。所以,关联数组不适合被用来存储需要按特定顺序处理的数据。
  2. 在使用[]来引用单个元素时,若在[]中使用变量,则不能省略$。
posted @ 2025-09-02 14:45  苍然满关中  阅读(15)  评论(0)    收藏  举报