数组实践
基础操作
数组基础
数组(Array)是有序的元素序列,它是数据结构在shell当中非常常见的一种数据存储方式,它将有限个类型相同的数据放到一个集合中,这个集合就是数组。为了操作方便,我们为数组定制一个名称变量,数组内的每一个数据都是数组元素,这些数组元素在集合中有顺序的观念,顺序的位置值我们称为下标
数组分类
数组样式-从数据结构的本身出发,它主要有多种数组样式
- 一维数组
- 一维数组是最简单的数组,按照顺序将一系列数据排列下来即可,数组本身没有场景含义
- 数据的表现样式:
数组[下标] - 适用场景:编程语言中基于数据的查询、聚合等操作
- 二维数组
- 二维数组是业务场景中常见的数组表现样式,即在一维数组的前提下,扩充了数据元素在场景中的含义
- 数据的表现样式:
数组[行下标][列下标] - 适用场景:数据库场景中基于数据的查询、聚合等操作
- 三维数组
- 三维数组是大型业务场景中通用的一种数组表现样式,它是在二维数据的前提下,扩充了数据空间的含义
- 数据的表现样式:
数组[行下标][列下标][页下标] - 适用场景:数据分析场景中基于数据的查询、聚合等操作
注意:
- bash支持一维数组(不支持多维数组),并且没有限定数组的大小。数组元素的下标由0开始编号
- 获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0
- bash的数组支持稀疏格式(索引名称可以不连续)
数组定义
数组创建
在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的语法格式:array_name=(value1 ... valuen)
注意:基于元素的格式,主要有单行定义、多行定义、单元素定义、命令定义等多种样式
语法解读
# 单行定义
array_name=(value0 value1 value2 value3)
# 多行定义
array_name=(
value0
value1
value2
value3
)
# 单元素定义,注意:单元素定义的时候,可以不使用连续的下标,而且下标的范围没有限制
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
# 命令定义就是value的值以命令方式来获取
file_array=($(ls /tmp/))
简单实践
# 实践1-单行定义
# 定制数据数组
num_list=(123,234,345,456,567)
echo ${num_list[0]}
123,234,345,456,567
# 数据元素之间使用空格隔开
num_list=(123 234 345 456 567)
echo ${num_list[0]}
123
echo ${num_list[@]}
123 234 345 456 567
# 实践2-多行定义
# 定制数组
class_one=(
> zhangsan
> lisi
> wangwu
> zhaoliu
> )
# 查看数组元素
echo ${class_one[0]}
zhangsan
echo ${class_one[@]}
zhangsan lisi wangwu zhaoliu
# 实践3-单元素定义
# 定制数组
mix_list[0]=nihao
mix_list[2]=345
mix_list[4]="1.23,4.56"
# 查看数组元素
echo ${mix_list[1]}
echo ${mix_list[@]}
nihao 345 1.23,4.56
# 批量多元素定义
string_list=([0]="value-1" [3]="value-2")
echo ${string_list[@]}
value-1 value-2
echo ${!string_list[@]}
0 3
# 实践4-命令定义
# 定制数组元素
unset file_array
# 注意:对于命令的数组创建来说,它只有一个元素(此时实际不是数组)
file_array=$(ls *.sh)
# 查看数组元素
echo ${file_array[0]}
count_head_feet.sh host_network_test.sh memory_info.sh simple_jumpserver.sh simple_login_string.sh site_healthcheck.sh test_argnum.sh
echo ${file_array[1]}
echo ${!file_array[@]}
0
unset file_array
# 这样创建数组,会是多个元素
file_array=($(ls *.sh))
echo ${file_array[0]}
count_head_feet.sh
echo ${file_array[@]}
count_head_feet.sh host_network_test.sh memory_info.sh simple_jumpserver.sh simple_login_string.sh site_healthcheck.sh test_argnum.sh
echo ${!file_array[@]}
0 1 2 3 4 5 6
数组取值
对于shell的数组数据来说,获取指定的数组元素主要有两种方法,一种是获取内容,一种是获取其他信息
语法解读
-
基于索引找内容,读取数组元素值可以根据元素的下标值来获取,语法格式如下:
${array_name[index]}${array_name[@]:起始位置:获取数量}
注意:获取具体的元素内容,指定其下标值,从0开始;获取所有的元素内容,下标位置写"@"或者"*"
-
获取数组索引,在找内容的时候,有时候不知道数组的索引都有哪些,我们可以基于如下方式来获取数组的所有索引,
${!array_name[@]}或${!array_name[*]} -
获取数组长度的方法与获取字符串长度的方法相同,格式如下:
${#array_name[index]}。注意:获取具体的元素长度,指定其下标值,从0开始;获取所有的元素个数,下标位置写"@"或者"*" -
从系统中获取所有的数组,
declare -a
简单实践
# 实践1-基于索引找内容
# 设定数组内容
num_list=(123 234 345 456 567)
# 获取指定位置元素
echo ${num_list[0]}
123
echo ${num_list[1]}
234
# 获取所有位置元素
echo ${num_list[*]}
123 234 345 456 567
echo ${num_list[@]}
123 234 345 456 567
# 获取末尾位置元素
echo ${num_list[-1]}
567
echo ${num_list[-2]}
456
# 获取指定范围元素
echo ${num_list[@]:1:1}
234
echo ${num_list[@]:1:3}
234 345 456
# 实践2-获取数组索引
echo ${!num_list[@]}
0 1 2 3 4
echo ${!num_list[*]}
0 1 2 3 4
# 实践3-获取数组长度
# 获取数组的元素数量
echo ${#num_list[@]}
5
echo ${#num_list[*]}
5
# 获取数据元素的长度
echo ${#num_list[3]}
3
# 实践4-获取系统所有数组
declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'
declare -a file_array='([0]="count_head_feet.sh" [1]="host_network_test.sh" [2]="memory_info.sh" [3]="simple_jumpserver.sh" [4]="simple_login_string.sh" [5]="site_healthcheck.sh" [6]="test_argnum.sh")'
declare -a num_list='([0]="123" [1]="234" [2]="345" [3]="456" [4]="567")'
数组变动
元素修改
数组元素的修改其实就是定义数组时候的单元素定义,主要包含两种,元素替换,元素部分内容替换,格式如下
- 元素内容替换,
array_name[index]=值,在修改元素的时候,index的值一定要保持准确 - 元素部分内容替换,
${array_name[index]/原内容/新内容},可以参考字符串替换格式。注意:默认是演示效果,原数组未被修改,如果真要更改需要结合单元素内容替换
# 修改指定位置的值
num_list[2]=aaa
echo ${num_list[@]}
123 234 aaa 456 567
# 替换元素值的特定内容
echo ${num_list[2]/aa/lualu-}
lualu-a
echo ${num_list[@]}
123 234 aaa 456 567
num_list[2]=${num_list[2]/aa/lualu-}
echo ${num_list[@]}
123 234 lualu-a 456 567
元素删除
将shell中的数组删除,可以使用unset来实现,主要有两种情况:删除单元素,删除整个数组。格式如下:
- 删除单元素,
unset array_name[index] - 删除整个数组,
unset array_name
# 删除指定的元素
echo ${num_list[@]}
123 234 lualu-a 456 567
unset num_list[2]
echo ${num_list[@]}
123 234 456 567
unset num_list[2]
echo ${num_list[@]}
123 234 456 567
# 删除数组中的元素,实际是将该下标位置置空,对其它位置没有影响
echo ${!num_list[@]}
0 1 3 4
unset num_list[1]
echo ${num_list[@]}
123 456 567
echo ${!num_list[@]}
0 3 4
# 删除整个数组
unset num_list
echo ${!num_list[@]}
综合实践
数组关联
上一节,我们学习了shell环境下的数组定制的简写方式。数组的定制主要有如下两种:
- 定制索引数组 - 数组的索引是普通的数字,
declare -a array_name,普通数组可以不事先声明,直接使用 - 定制关联数组 - 数组的索引是自定义的字母,
declare -A array_name,关联数组必须先声明,再使用
# 实践1-定制索引数组
# 定制一个空内容的数组
declare -a course
declare -a | grep course
declare -a course='()'
# 定制一个包含元素的数组
course=(yuwen shuxue yingyu)
declare -a | grep course
declare -a course='([0]="yuwen" [1]="shuxue" [2]="yingyu")'
# 实践2-定制关联数组
# 定制关联数组
declare -A score
declare -a | grep score
declare -A | grep score
declare -A score='()'
# 关联数组和数字索引数组不能通用
declare -a score
-bash: declare: score: cannot convert associative to indexed array
# 关联数组的操作
score[yingyu]="32"
score[yuwen]="67"
score[shuxue]="65"
declare -A | grep score
declare -A score='([yingyu]="32" [yuwen]="67" [shuxue]="65" )'
echo ${!score[@]}
yingyu yuwen shuxue
echo ${score[@]}
32 67 65
数组案例
信息统计
需求
分别打印CPU 1min 5min 15min load负载值;命令提示:uptime 信息显示: CPU 1 min平均负载为: 0.00 CPU 5 min平均负载为: 0.01 CPU 15 min平均负载为: 0.05
cpu_load.sh,创建脚本文件,内容如下
#!/bin/bash
# 功能:采集系统cpu负载信息
# 版本:v0.1
# 作者:example
# 联系:www.example.com
# 获取CPU负载情况
cpu_load=($(uptime | tr -s " " | cut -d " " -f 11-13 | tr "," " "))
# 信息输出
echo -e "\e[31m\t系统cpu负载信息\e[0m"
echo -e "\e[32m================================"
echo "CPU 1 min平均负载为: ${cpu_load[0]}"
echo "CPU 5 min平均负载为: ${cpu_load[1]}"
echo "CPU 15 min平均负载为: ${cpu_load[2]}"
echo -e "================================\e[0m"
/bin/bash cpu_load.sh
系统cpu负载信息
================================
CPU 1 min平均负载为: 0.00
CPU 5 min平均负载为: 0.01
CPU 15 min平均负载为: 0.05
================================
服务管理
需求
服务的管理动作有:"启动" "关闭" "重启" "重载" "状态" 服务的管理命令有:"start" "stop" "restart" "reload" "status" 选择不同的动作,输出不同的服务执行命令,格式如下:systemctl xxx service_name
service_manager.sh,创建脚本文件,内容如下
#!/bin/bash
# 功能:定制服务管理的功能
# 版本:v0.1
# 作者:example
# 联系:www.example.com
# 定制普通数组
oper_array=(启动 关闭 重启 重载 状态)
# 定制关联数组
declare -A cmd_array
cmd_array=([启动]=start [关闭]=stop [重启]=restart [重载]=reload [状态]=status)
# 服务的操作提示
echo -e "\e[31m---------------服务的操作动作---------------
1: 启动 2: 关闭 3: 重启 4: 重载 5: 状态
--------------------------------------------"'\033[0m'
# 选择服务操作类型
read -p "> 请输入服务的操作动作: " oper_num
echo
echo -e "\e[31m您选择的服务操作动作是: ${oper_array[$oper_num-1]}\e[0m"
echo -e "\e[32m===============服务的执行动作===============
您即将对服务执行如下命令:
\tsystemctl ${cmd_array[${oper_array[$oper_num-1]}]} service_name
=========================================="'\033[0m'
/bin/bash service_manager.sh
---------------服务的操作动作---------------
1: 启动 2: 关闭 3: 重启 4: 重载 5: 状态
--------------------------------------------
> 请输入服务的操作动作: 1
您选择的服务操作动作是: 启动
===============服务的执行动作===============
您即将对服务执行如下命令:
systemctl start service_name
==========================================