Shell编程之数组

本文主要对Shell中的数组进行简单总结,另外本文所使用的Linux环境为CentOS Linux release 8.1.1911,所使用的Shell为bash 4.4.19(1)-release

一、定义数组

Shell支持数组,即一组数据的集合,里面的每个数据被称为一个数组元素。当前Bash仅支持一维索引数组和关联数组,对数组的长度(元素个数)没有限制,也没有对索引和成员分配要连续的要求。使用内置命令declare可以显示声明一个数组:

# 显式声明一个数组,name表示数组名
declare -a name
# 这种语法下标会被忽略
declare -a name[subscript]

1.定义索引数组

任何变量都可以用作索引数组,索引数组使用整数(包括算术表达式)进行引用(reference),并且索引从0开始,除非另有说明,索引数组索引必须是非负整数。

使用以下语法给任意变量赋值会自动创建一个索引数组:

# 会自动创建一个索引数组,数组名为name,下标被视为一个算术表达式,其结果必须为数字
name[subscript]=value

示例如下:
1
使用以下复合赋值语句可以定义数组并赋值:

# 对于索引数组,下标([subscript1]=)是可选的,如果指定了下标,则赋值给指定下标的元素
# 否则要赋值元素的下标是该语句所赋值的最后一个下标加1,下标从0开始
name=([subscript1]=value1 [subscript2]=value2 … )

使用复合赋值语句不指定下标的定义索引数组的示例如下:
2

数组元素的类型可以不同。

先定义一个列表形式的字符串,然后在()中引用该字符串也可以定义数组,示例如下:
3
使用复合赋值语句指定下标的定义索引数组的示例如下:
4

上例只给3个指定下标的元素赋值,所以数组长度为3。${name[*]}获取数组所有元素,${#name[*]}获取数组长度。

2.定义关联数组

关联数组使用任意字符串来访问元素。关联数组用下面的形式来创建:

# 声明一个关联数组(必须先声明为关联数组)
declare -A name
# 可以使用单独给各个元素赋值的方式创建关联数组
name[subscript]=value
# 或者使用复合赋值语句创建数组并赋值
# 对于关联数组,下标是必须的,使用键值对时,键不能缺失和为空,最后的缺失值被视为空字符串
name=([subscript1]=value1 [subscript2]=value2 … )

# 也可以在声明的同时给数组赋值
declare -A name[subscript]=value
declare -A name=([subscript1]=value1 [subscript2]=value2 … )

使用单独给各个元素赋值的方式创建关联数组的示例如下:
5
使用复合赋值语句定义关联数组的示例如下:
6
在声明关联数组的同时给数组赋值的示例如下:
7

内部命令declarelocalreadonly都接受-a选项来指定索引数组,以及一个-A选项来指定关联数组。如果两个选项都有,则优先使用-A。内部命令read程序接受一个-a选项,将从标准输入中读取一组单词分配给数组,并且可以从标准输入读取值后赋给单个数组元素。内置命令setdeclare可以以允许将数组值作为输入重用的方式显示数组值。

二、获取数组元素

1.获取单个元素的值

获取数组中单个元素的值的语法如下:

# 获取名为name的数组下标为subscript的元素的值,对于索引数组,下标大于等于0
# 对于索引数组,如果下标小于0,则索引从数组末尾开始计数,索引-1引用最后一个元素
# 如果省略下标,则获取下标为0的元素
${name[subscript]}

获取索引数组中单个元素的值的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
# 输出数组中下标为0的元素的值
echo ${array[0]}
# 引用不带下标的数组变量等效于使用下标0的引用,也是输出数组中下标为0的元素的值
echo ${array}
# 输出数组中下标为2的元素的值
echo ${array[2]}
# 输出数组中最后1个元素的值
echo ${array[-1]}
# 输出数组中倒数第3个元素的值
echo ${array[-3]}

执行结果:
8
获取关联数组中单个元素的值的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
# 输出数组中下标为uid的元素的值
echo ${account["uid"]}
# 输出数组中下标为username的元素的值
echo ${account["username"]}
# 输出数组中下标为email的元素的值
echo ${account["email"]}

执行结果:
9

使用有效下标对变量的任何引用都是合法的,并且bash会在必要时创建一个数组。如果已为下标分配了值,则认为已设置数组变量。

2.获取所有元素的值

获取数组中所有元素的值的语法如下:

# 都是获取名为name的数组中所有元素的值,如果数组中没有元素,则结果为空
# 只有在被双引号包围时,*和@才有所不同
# 被双引号包围时,${name[*]}扩展为一个单词,每个数组元素的值都由IFS的第一个字符分隔(一般是空格),而${name[@]}仍将数组中每个元素的值都扩展为独立的单词
${name[*]}
${name[@]}

获取索引数组中所有元素的值的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
# 使用${name[*]}语法输出数组中所有元素的值
echo ${array[*]}
# 使用${name[@]}语法输出数组中所有元素的值
echo ${array[@]}

执行结果:
10
获取关联数组中所有元素的值的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
# 使用${name[*]}语法输出数组中所有元素的值
echo ${account[*]}
# 使用${name[@]}语法输出数组中所有元素的值
echo ${account[@]}

执行结果:
11
以下示例可以看出${name[*]}${name[@]}的区别:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)

echo "循环打印\${array[*]}中的每个元素"
for var in ${array[*]}
do
    echo ${var}
done

echo "循环打印\${array[@]}中的每个元素"
for var in ${array[@]}
do
    echo ${var}
done

echo "循环打印\"\${array[*]}\"中的每个元素"
for var in "${array[*]}"
do
    echo ${var}
done

echo "循环打印\"\${array[@]}\"中的每个元素"
for var in "${array[@]}"
do
    echo ${var}
done

执行结果:
12

3.获取所有元素的下标

获取数组中所有元素的下标(索引)的语法如下:

# 获取名为name的数组中所有元素的下标,双引号中的处理与特殊参数*和@类似
# 所以${!name[*]}和${!name[@]}的区别与上面的${name[*]}和${name[@]}的区别类似
${!name[*]}
${!name[@]}

获取索引数组中所有元素的下标的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
# 使用${!name[*]}语法输出数组中所有元素的下标
echo ${!array[*]}
# 使用${!name[@]}语法输出数组中所有元素的下标
echo ${!array[@]}

执行结果:
13
获取关联数组中所有元素的下标的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
# 使用${!name[*]}语法输出数组中所有元素的下标
echo ${!account[*]}
# 使用${!name[@]}语法输出数组中所有元素的下标
echo ${!account[@]}

执行结果:
14

三、获取数组及数组元素长度

1.获取数组长度

获取数组长度的语法如下:

# 获取名为name的数组的长度(数组中元素个数)
${#name[*]}
${#name[@]}

获取数组长度的示例如下:

#!/bin/bash

# 获取索引数组长度示例
array=("hello" "shell" 123 "java" "abc" 321)
# 使用${#name[*]}语法输出数组长度
echo ${#array[*]}
# 使用${#name[@]}语法输出数组长度
echo ${#array[@]}

# 获取关联数组长度示例
declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
# 使用${#name[*]}语法输出数组长度
echo ${#account[*]}
# 使用${#name[@]}语法输出数组长度
echo ${#account[@]}

执行结果:
15

2.获取指定数组元素的长度

获取数组中指定元素的长度的语法如下:

# ${#name[subscript]}会扩展为${name[subscript]}的长度,即名为name的数组中指定元素的长度(字符个数)
# 如果没有指定下标,则相当于指定了0作为下标
${#name[subscript]}

获取索引数组中指定元素的长度的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
# 输出数组中下标为0的元素的长度
echo ${#array[0]}
# 没有指定下标,则相当于指定了0作为下标,也是输出数组中下标为0的元素的长度
echo ${#array}
# 输出数组中下标为2的元素的长度
echo ${#array[2]}
# 输出数组中最后1个元素的长度
echo ${#array[-1]}
# 输出数组中倒数第3个元素的长度
echo ${#array[-3]}

执行结果:
16
获取关联数组中指定元素的长度的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
# 输出数组中下标为uid的元素的长度
echo ${#account["uid"]}
# 输出数组中下标为username的元素的长度
echo ${#account["username"]}
# 输出数组中下标为email的元素的长度
echo ${#account["email"]}

执行结果:
17

四、修改数组元素

可以使用单独给元素赋值的方式来修改数组中指定元素的值:

# 通过给单个元素赋值的方式来修改数组中指定元素的值
# 指定的下标不存在会添加元素
name[subscript]=value

修改索引数组中指定元素的值的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
echo ${array[*]}
# 修改数组中下标为0的元素的值
array[0]="world"
echo ${array[*]}
# 没有指定下标,则相当于指定了0作为下标,也是修改数组中下标为0的元素的值
array="hello"
echo ${array[*]}
# 修改数组中下标为2的元素的值
array[2]=111
echo ${array[*]}
# 修改数组中最后1个元素的值
array[-1]=333
echo ${array[*]}
# 修改数组中倒数第3个元素的值
array[-3]="c++"
echo ${array[*]}

执行结果:
18
修改关联引数组中指定元素的值的示例:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
echo ${account["uid"]} ${account["username"]} ${account["email"]}
# 修改数组中下标为uid的元素的值
account["uid"]="u0212348"
echo ${account["uid"]} ${account["username"]} ${account["email"]}
# 修改数组中下标为username的元素的值
account["username"]="zhangsan02"
echo ${account["uid"]} ${account["username"]} ${account["email"]}
# 修改数组中下标为email的元素的值
account["email"]="zhangsan02@xxx.com"
echo ${account["uid"]} ${account["username"]} ${account["email"]}

执行结果:
19

五、添加数组元素

1.通过下标添加元素

可以通过使用下标给单个元素赋值的方式添加数组元素:

# 通过给单个元素赋值的方式添加元素,需要确保下标subscript处没有值,否则将修改该下标处的值,每次只能添加一个元素
# subscript=${#name[*]}或${#name[@]}时,是以数组长度为下标添加,注意下标要连续,否则可能会替换掉已有元素
name[subscript]=value

通过下标向索引数组添加元素的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为6,值为"bcd"
array[6]="bcd"
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为数组长度,值为666
array[${#array[*]}]=666
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为数组长度,值为"c++"
array[${#array[@]}]="c++"
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为10,值为"bash"
array[10]="bash"
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 由于数组不连续,下标为10的元素的值将被修改为"dash"
array[${#array[@]}]="dash"
echo ${!array[*]}
echo ${array[*]}

执行结果:
20
通过下标向关联数组添加元素的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为"tel",值为"19912312312"
account["tel"]="19912312312"
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为数组长度,值为"hello"
account[${#account[*]}]="hello"
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为数组长度,值为"world"
account[${#account[@]}]="world"
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 添加一个数组元素,下标为"9",值为123
account["9"]=123
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 这里下标为"9"的元素的值会被修改为321
account[${#account[@]}]=321
echo ${!account[*]}
echo ${account[*]}

执行结果:
21

2.重新创建数组添加元素

语法如下:

# 适用于索引数组,这种方式会重置数组中原有的下标,从0开始变成连续下标
# 双引号不能省略,否则当原数组中存在包含空格的元素时会按空格将元素拆分成多个
# 不能将@替换为*,如果替换为*,"${name[@]}"会将所有元素当作一个元素添加到数组中
name=("${name[@]}" value1 value2 ... )

通过该方式向索引数组添加元素的示例如下:

#!/bin/bash

array=([1]="hello" [3]="shell" [5]=123 [7]="java" [9]="abc" [11]=321)
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 向数组中添加元素"bbb ccc"、666、"c++",原数组中下标不连续,在添加元素后会重置下标,从0开始连续递增
array=("${array[@]}" "bbb ccc" 666 "c++")
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 向数组中添加元素"bash"、333
# ${array[@]}没有用双引号包围,原数组中的"bbb ccc"会拆分成"bbb"、"ccc"
array=(${array[@]} "bash" 333)
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 向数组中添加元素"sh"、"python"
# @替换为了*,原数组中的所有元素会被当成一个元素添加到数组中
array=("${array[*]}" "sh" "python")
echo ${!array[*]}
echo ${array[*]}

执行结果:
22

3.使用+=运算符添加元素

语法如下:

# 添加元素后不会重置原数组下标
# 对于索引数组,如果不指定下标,则新添加元素的下标从原数组最后一个有值元素的下标加1开始连续递增
# 对于关联数组,必须指定下标
name+=([subscript1]=value1 [subscript2]=value2 … )

通过该方式向索引数组添加元素的示例如下:

#!/bin/bash

array=([1]="hello" [3]="shell" [5]=123 [7]="java" [9]="abc" [11]=321)
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 向数组中添加下标为13的元素"bbb ccc"、下标为15的元素666、下标为17的元素"c++"
array+=([13]="bbb ccc" [15]=666 [17]="c++")
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 向数组中添加元素"bash"、333,不指定下标
array+=("bash" 333)
echo ${!array[*]}
echo ${array[*]}

执行结果:
23
通过该方式向关联数组添加元素的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 向数组中添加下标为"tel"的元素"19912312312"、下标为"area"的元素"shanghai"、下标为"job"的元素"engineer"
account+=(["tel"]="19912312312" ["area"]="shanghai" ["job"]="engineer")
echo ${!account[*]}
echo ${account[*]}

执行结果:
24

六、删除数组元素和数组

1.删除数组元素

删除数组中指定元素的语法如下:

# 删除名为name的数组中下标为subscript的元素,对于索引数组,下标大于等于0
# 索引数组中的负下标从数组末尾开始计数,索引-1表示最后一个元素,这里就删除最后一个元素
unset name[subscript]

删除索引数组中指定元素的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 删除数组中下标为0的元素
unset array[0]
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 删除数组中下标为1的元素
unset array[1]
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 删除数组中最后1个元素
unset array[-1]
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 删除数组中倒数第3个元素
unset array[-3]
echo ${!array[*]}
echo ${array[*]}

执行结果:
25
删除关联数组中指定元素的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 删除数组中下标为"uid"的元素
unset account["uid"]
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 删除数组中下标为"username"的元素
unset account["username"]
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 删除数组中下标为"email"的元素
unset account["email"]
echo ${!account[*]}
echo ${account[*]}

执行结果:
26

2.删除数组

删除整个数组的语法如下:

# name为一个数组的话就删除整个名为name的数组
unset name
unset name[*]
unset name[@]

删除整个数组的示例如下:

#!/bin/bash

# 删除索引数组示例
array=("hello" "shell" 123 "java" "abc" 321)
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 删除整个数组
unset array
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
array=("hello" "shell" 123 "java" "abc" 321)
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"
# 删除整个数组
unset array[*]
echo ${!array[*]}
echo ${array[*]}
echo "---------------------------------------"

# 删除关联数组示例
declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
echo ${!account[*]}
echo ${account[*]}
echo "---------------------------------------"
# 删除整个数组
unset account[@]
echo ${!account[*]}
echo ${account[*]}

执行结果:
27

七、遍历数组

1.直接遍历数组元素的值

直接遍历数组元素的值:

for v in ${name[@]}
do
    echo ${v}
done

直接遍历数组元素的值的示例如下:

#!/bin/bash

array=("hello" "shell" 123 "java" "abc" 321)
# 直接遍历数组元素的值
for v in ${array[@]}
do
    echo ${v}
done

执行结果:
28

2.通过下标遍历数组

通过下标遍历数组:

for i in ${!name[@]}
do
    echo "${i} : ${name[${i}]}"
done

通过下标遍历数组的示例如下:

#!/bin/bash

declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
# 通过下标遍历数组
for i in ${!account[@]}
do
    echo "${i} : ${account[${i}]}"
done

执行结果:
29

3.C语言风格的for循环遍历数组

通过C语言风格的for循环遍历数组:

# 只适用于下标从0开始并且连续的索引数组
for (( i=0; i<${#name[@]}; i++ ))
do
    echo ${name[${i}]}
done

通过C语言风格for循环遍历索引数组的示例如下:

#!/bin/bash

array=("aaa" "bbb" "ccc" "ddd" "eee" "fff")
# 通过C语言风格的for循环遍历索引数组
for (( i=0; i<${#array[@]}; i++ ))
do
    echo ${array[${i}]}
done

执行结果:
30

4.while循环遍历数组

通过while循环遍历数组:

# 只适用于下标从0开始并且连续的索引数组
i=0
#-lt 小于
while [ ${i} -lt ${#name[@]} ]
do
    echo ${name[${i}]}
    let i++
done

通过while循环遍历索引数组的示例如下:

#!/bin/bash

array=("sh" "bash" "csh" "ksh" "dash" "zsh")
# 通过while循环遍历索引数组
i=0
while [ ${i} -lt ${#array[@]} ]
do
    echo ${array[${i}]}
    let i++
done

执行结果:
31

5.until循环遍历数组

通过until循环遍历数组:

# 只适用于下标从0开始并且连续的索引数组
i=0
# -eq 等于
until [ ${i} -eq ${#name[@]} ]
do
    echo ${name[${i}]}
    let i++
done

通过until循环遍历索引数组的示例如下:

#!/bin/bash

array=("c" "c++" "java" "python" "sacla" "swift")
# 通过until循环遍历索引数组
i=0
# -eq 等于
until [ ${i} -eq ${#array[@]} ]
do
    echo ${array[${i}]}
    let i++
done

执行结果:
32

八、数组合并

数组合并就是将两个数组拼接成一个数组,语法如下:

# 会重置原数组中的下标,新数组的下标从0开始连续递增
array3=(${array1[@]} ${array2[@]})
array3=(${array1[*]} ${array2[*]})

数组合并的示例如下:

#!/bin/bash

# 合并索引数组
array1=([1]="c" [3]="c++" [5]="java" [7]="python" [9]="sacla" [11]="swift")
array2=([2]="sh" [4]="bash" [6]="csh" [7]="ksh" [9]="dash" [10]="zsh")
array3=(${array1[@]} ${array2[@]})
echo ${!array3[@]}
echo ${array3[@]}
echo "---------------------------------------"

# 合并关联数组
declare -A account=(["uid"]="a123776" ["username"]="zhangsan01" ["password"]="qwer123" ["age"]=22 ["email"]="zhangsan01@xxx.com")
declare -A order=(["orderid"]="11223344" ["ordername"]="iphone" ["price"]="8888")
account_order=(${account[*]} ${order[*]})
echo ${!account_order[@]}
echo ${account_order[@]}

执行结果:
33
合并之后下标重置了,新数组下标从0开始连续递增。关联数组合并之后下标也重置为从0开始连续递增的数字,变成了索引数组。

九、数组切片

对数组进行截取的语法如下:

# 对于索引数组,length>=0,则从name[offset]开始,向右截取length个元素,如果不指定length,则截取到数组末尾元素
# offset<0时,索引是从数组末尾开始计数,索引-1表示从最后一个元素,负数的offset与:至少保持一个空格,避免与:-混淆
# length<0,则会报错,对于关联数组,会产生未定义的结果
${name[@]:offset:length}
${name[*]:offset:length}

对索引数组进行截取的示例如下:

#!/bin/bash

array=(0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h)
# 从数组中下标为7的元素开始向右截取2个元素
echo ${array[@]:7:2}
# 从数组中下标为7的元素开始向右截取到最后一个元素
echo ${array[*]:7}
# 从数组中倒数第7的元素开始向右截取2个元素
echo ${array[@]: -7:2}
# 从数组中倒数第7的元素开始向右截取0个元素
echo ${array[*]: -7:0}
# length<0,会报错
echo ${array[@]: -7:-2}

执行结果:
34
还可以通过模式匹配(pattern matching)对数组中的每个元素进行截取,语法如下:

# 数组下标为*和@一样,这里省略,word可以被扩展为一个模式(pattern),通过模式匹配规则进行匹配
# 模式删除操作对数组元素依次执行,扩展结果就是所得到的数组元素列表
# 对数组元素依次执行,从左边开始匹配并将最短匹配部分删除,返回剩余部分
${name[@]#word}
# 对数组元素依次执行,从左边开始匹配并将最长匹配部分删除,返回剩余部分
${name[@]##word}
# 对数组元素依次执行,从右边开始匹配并将最短匹配部分删除,返回剩余部分
${name[@]%word}
# 对数组元素依次执行,从右边开始匹配并将最长匹配部分删除,返回剩余部分
${name[@]%%word}

通过模式匹配对数组中的每个元素进行截取的示例如下:

#!/bin/bash

array=("https://blog.csdn.net/RtxTitanV" "https://kubernetes.io/docs/home" "https://gitee.com/RtxTitanV" "https://github.com/RtxTitanV")
# 对数组元素依次执行,从左开始匹配并删除第一个匹配到*/的所有字符
echo ${array[*]#*/}
# 对数组元素依次执行,从左开始匹配并删除最后一个匹配到*/的所有字符
echo ${array[@]##*/}
# 对数组元素依次执行,从右开始匹配并删除第一个匹配到/*的所有字符
echo ${array[*]%/*}
# 对数组元素依次执行,从右开始匹配并删除最后一个匹配到/*的所有字符
echo ${array[@]%%/*}

执行结果:
35

十、数组替换

对数组中的元素进行替换的语法如下:

# pattern为一个模式,替换会对数组元素依次执行,将元素中与模式匹配的最长部分替换为指定字符串
# 如果模式以/开头,则所有与之匹配的部分都会用字符串替代,通过情况只替换第一个匹配的部分
# 如果模式以#开头,则只能从左往右匹配
# 如果模式以%开头,则只能从右往左匹配
# 如果字符串为空,则与模式匹配的部分将被删除,这时,模式后面的/可以省略
${name[@]/pattern/string}
${name[*]/pattern/string}

对数组中的元素进行替换的示例如下:

#!/bin/bash

array=("https://blog.csdn.net/RtxTitanV" "https://blog.nete.net/docs/home/RtxTitanV" "https://blog.asda.com/RtxTitanV" "https://blog.rhub.com/RtxTitanV")
# 对数组元素依次执行,将第一个与.匹配的部分替换为/,即将第一个.替换为/
echo ${array[@]/./"/"}
echo "---------------------------------------"
# 对数组元素依次执行,将所有与.匹配的部分替换为/,即将所有.替换为/
echo ${array[*]//./"/"}
echo "---------------------------------------"
# 对数组元素依次执行,从左往右匹配,将与h*s匹配的最长部分替换为http
echo ${array[@]/#h*s/"http"}
echo "---------------------------------------"
# 对数组元素依次执行,从右往左匹配,将与.*匹配的最长部分替换为/home
echo ${array[*]/%.*/"/home"}
echo "---------------------------------------"
# 对数组元素依次执行,将所有与.匹配的部分删除,即将所有.删除
echo ${array[@]//.}

执行结果:
36
转换数组中元素大小写的语法如下:

# 数组下标为*和@一样,这里省略,pattern为一个模式,如果省略pattern,则与每个字符匹配(相当于?)
# 对数组元素依次执行,把与pattern匹配的第一个字符转换为大写字符
${name[@]^pattern}
# 对数组元素依次执行,把与pattern匹配的所有字符转换为大写字符
${name[@]^^pattern}
# 对数组元素依次执行,把与pattern匹配的第一个字符转换为小写字符
${name[@],pattern}
# 对数组元素依次执行,把与pattern匹配的所有字符转换为小写字符
${name[@],,pattern}

转换数组中元素大小写的示例如下:

#!/bin/bash

array=("character" "EXISTENCE" "Command" "EXPANSION" "substitution" "SUBSCRIPTE" "exclamation" "Introduce" "exception" "indirection")
# 对数组元素依次执行,将与e匹配的首字母转换为大写
echo ${array[@]^e}
echo "---------------------------------------"
# 对数组元素依次执行,将首字母转换为大写,等价于${array[@]^?}
echo ${array[*]^}
echo "---------------------------------------"
# 对数组元素依次执行,将首字母转换为大写
echo ${array[@]^?}
echo "---------------------------------------"
# 对数组元素依次执行,将与[ces]匹配的首字母转换为大写
echo ${array[*]^[ces]}
echo "---------------------------------------"
# 对数组元素依次执行,将所有字符转换为大写
echo ${array[@]^^}
echo "---------------------------------------"
# 对数组元素依次执行,将与[ces]匹配的所有字符转换为大写
echo ${array[*]^^[ces]}
echo "---------------------------------------"
# 对数组元素依次执行,将与E匹配的首字母转换为小写
echo ${array[@],E}
echo "---------------------------------------"
# 对数组元素依次执行,将首字母转换为小写,等价于${array[@],?}
echo ${array[*],}
echo "---------------------------------------"
# 对数组元素依次执行,将与[CES]匹配的首字母转换为小写
echo ${array[@],[CES]}
echo "---------------------------------------"
# 对数组元素依次执行,将所有字符转换为小写
echo ${array[*],,}
echo "---------------------------------------"
# 对数组元素依次执行,将与[CES]匹配的所有字符转换为小写
echo ${array[@],,[CES]}

执行结果:
37

以上数组切片和数组替换操作都不会改变原数组的内容,如果要改变原数组的内容,只需重新定义即可,例如${name[@]/pattern/string}并不会改变name数组,要改变name数组,只需重新定义,即name=(${name[@]/pattern/string})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Shell字符串数组是一种存储多个字符串的数据结构,可以通过下标访问数组中的元素,也可以通过循环遍历数组中的所有元素。在Shell脚本中,可以使用declare命令或者直接赋值的方式来创建字符串数组。例如,使用declare命令创建一个包含三个字符串的数组: declare -a arr=("hello" "world" "shell") 然后可以通过下标访问数组中的元素: echo ${arr[]} # 输出hello 也可以使用循环遍历数组中的所有元素: for i in "${arr[@]}" do echo $i done 输出结果为: hello world shell ### 回答2: Shell中的字符串数组是一种特殊的变量类型,用于存储多个字符串。在Shell脚本中,字符串数组可以用于存储一系列相关的字符串,并且可以对其进行遍历、操作和处理。 定义字符串数组可以使用以下语法: ``` array=("string1" "string2" "string3") ``` 其中,array是数组的名称,而"string1"、"string2"、"string3"是数组中的元素。 也可以逐个添加元素到数组中: ``` array[0]="string1" array[1]="string2" array[2]="string3" ``` 访问数组元素可以使用以下语法: ``` element=${array[index]} ``` 其中,index是数组中元素的索引,element是获取的数组元素。 对于数组的长度,可以使用以下语法: ``` length=${#array[@]} ``` 使用这个语法,可以获取数组中元素的个数。 遍历字符串数组可以使用循环语句: ``` for element in "${array[@]}" do echo $element done ``` 这个例子中,通过遍历${array[@]},我们可以访问数组中的每个元素,并将其打印出来。 使用字符串数组,可以方便地存储和处理一系列相关的字符串数据,从而实现更加灵活和高效的脚本编写。 ### 回答3: Shell字符串数组Shell编程语言中的一种数据结构,它可以存储多个字符串,并通过索引访问和操作。在Shell中,字符串数组可以通过以下方式定义和初始化: ```bash my_array=("string1" "string2" "string3") ``` 上述代码定义了一个名为my_array的字符串数组,其中有三个元素,分别是"string1"、"string2"和"string3"。我们可以通过数组索引来访问特定的元素,如: ```bash echo ${my_array[0]} # 输出第一个元素"string1" echo ${my_array[1]} # 输出第二个元素"string2" echo ${my_array[2]} # 输出第三个元素"string3" ``` 我们还可以通过下标的方式遍历整个数组,并对每个元素进行操作,如: ```bash for element in ${my_array[@]}; do echo $element done ``` 上述代码会将数组中的每个元素逐行输出。 在Shell中,我们可以使用数组来存储需要进行批量处理的数据,方便对多个字符串进行统一操作,比如切割、连接等。同时,字符串数组还可以作为函数的参数传递,方便将多个字符串作为一个整体进行处理。总的来说,Shell字符串数组是一种非常有用的数据结构,可以简化Shell脚本编写,提高代码的可读性和维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RtxTitanV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值