使用Shell数组

使用Shell数组

问题

本案例要求编写一个Shell脚本getips.sh,相关要求如下:
能够反复从键盘输入IP地址,保存到数组
当用户输入“EOF”后结束输入,显示数组IPADDS各元素的值
最后报告本次录入的IP地址个数、其中第1个录入的地址

方案

建立数组的方法:
格式1,整体赋值:数组名=(值1 值2 … … 值n)
格式2,单个元素赋值:数组名[下标]=值
查看数组元素的方法:
获取单个数组元素: 数 组 名 [ 下 标 ] 获 取 所 有 数 组 元 素 : {数组名[下标]} 获取所有数组元素: []{数组名[@]}
获取数组元素个数:KaTeX parse error: Expected '}', got '#' at position 2: {#̲数组名[@]} 获取连续的多个…{数组名[@]:起始下标:元素个数}
获取某个数组元素的长度:KaTeX parse error: Expected '}', got '#' at position 2: {#̲数组名[下标]} 截取数组元素…{#数组名[下标]:起始下标:字符数}

步骤

实现此案例需要按照如下步骤进行。
步骤一:认识数组的赋值/引用基本方法
1)declare命令的使用
在Shell环境中,变量默认均作为字符串处理,当参与expr、 [ ] 数 学 运 算 时 自 动 作 为 整 数 处 理 。 比 如 , 使 用 “ 1 + 2 ” 、 “ X + 2 ” 、 “ []数学运算时自动作为整数处理。比如,使用“1+2”、“X+2”、“ []使1+2X+2X+2”表达式是无法将运算结果直接作为整数赋值给指定的变量的:

[root@svr5 ~]# X=24
[root@svr5 ~]# A=1+2
[root@svr5 ~]# echo $A
1+2  								//赋值结果为字符串
[root@svr5 ~]# A=X+2
[root@svr5 ~]# echo $A
X+2  								//赋值结果为字符串
[root@svr5 ~]# A=$X+2
[root@svr5 ~]# echo $A
24+2  								//赋值结果为字符串

上述操作中,变量A均作为字符串处理。
若要将一个变量强制设置为整数,可以使用declare命令声明(-i选项):

[root@svr5 ~]# declare -i A  		//先将A声明为整数变量
[root@svr5 ~]# A=1+2  				//然后赋值
[root@svr5 ~]# echo $A  				//确认结果
3
[root@svr5 ~]# declare -i B=$X+2  	//也可以在声明的同时进行赋值
[root@svr5 ~]# echo $B
26

declare命令结合-x选项,可以将局部变量设置为全局变量,这个与export命令的作用差不多:

[root@svr5 ~]# declare -x NM="Tarena"  	//新建全局变量NM
[root@svr5 ~]# bash  					//进入子Shell环境
[root@svr5 ~]# echo $NM  				//验证全局变量
Tarena
[root@svr5 ~]# exit  					//返回到原Shell环境
exit
[root@svr5 ~]#

如果要取消变量的全局属性,可以使用“+x”选项:

[root@svr5 ~]# declare +x NM  			//将NM恢复为局部变量
[root@svr5 ~]# bash  					//进入子Shell环境
[root@svr5 ~]# echo $NM  				//检查已无法调用NM变量

[root@svr5 ~]# exit  					//返回到原Shell环境
exit
[root@svr5 ~]#

declare命令结合-r选项,可以为变量设置“只读”属性,只读变量的值不允许再被修改,通常可用来保存一些固定的参数,避免无意中被修改:

[root@svr5 ~]# echo $NM
Tarena
[root@svr5 ~]# declare -r NM  				//将变量NM设置为只读
[root@svr5 ~]# NM="Tarena IT Group."  		//重新赋值失败
-bash: NM: readonly variable
[root@svr5 ~]# echo $NM  					//查看还是原来的值
Tarena

只读变量除了不能修改值以外,也无法被unset清除(若要清除只读变量,需要退出当前Shell程序):

[root@svr5 ~]# unset NM
-bash: unset: NM: cannot unset: readonly variable
[root@svr5 ~]# echo $NM
Tarena

2)定义/赋值数组
使用declare命令,结合-a选项可声明一个数组(这个操作一般可不做),比如:

[root@svr5 ~]# declare -a SVRS

直接执行declare -a,即不指定数组名参数时,会列出当前Shell环境中已定义的所有数组设置:

[root@svr5 ~]# declare -a  				//查看已定义的数组
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="3" [1]="2" [2]="25" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FQDNS='([0]="www.tarena.com" [1]="mail.tarena.com" [2]="club.tarena.com")'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0" [1]="0")'
declare -a SVRS='([0]="www" [1]="ftp" [2]="mail" [3]="club")'

若要定义数组的成员,可以在declare声明时定义,也可以直接整体定义。整体赋值的格式为“数组名=(值1 值2 值3 … …)”,比如:

[root@svr5 ~]# MY_SVRS=(www ftp mail club)
[root@svr5 ~]# set | grep "MY_"  			//查看数组定义结果
MY_SVRS=([0]="www" [1]="ftp" [2]="mail" [3]="club")

Shell中的语法要求是比较松散的,所以我们也可以直接为单个数组元素赋值,格式为“数组名[下标]=值”,每个数组元素的编号(即下标)从0开始。比如,以下操作会产生一个包括3个元素的数组:

[root@svr5 ~]# WEB_SVRS[0]="www.tarena.com"  		//为第1个元素赋值
[root@svr5 ~]# WEB_SVRS[1]="mail.tarena.com"  		//为第2个元素赋值
[root@svr5 ~]# WEB_SVRS[2]="club.tarena.com"  		//为第3个元素赋值
[root@svr5 ~]# set | grep "WEB_"  				//查看数组定义
WEB_SVRS=([0]="www.tarena.com" [1]="mail.tarena.com" 
[2]="club.tarena.com")

为数组元素赋值时,并不要求每个成员都需要指定,下标也可以不连续。比如,可跳过下标3,直接为下标为4的元素赋值:

[root@svr5 ~]# WEB_SVRS[4]="tts6.tarena.com"
[root@svr5 ~]# set | grep "WEB_"  				//确认设置结果
WEB_SVRS=([0]="www.tarena.com" [1]="mail.tarena.com" [2]="club.tarena.com" [4]="tts6.tarena.com")

3)查看数组、查看数组元素
输出整个数组的内容:

[root@svr5 ~]# echo ${MY_SVRS[@]}
www ftp mail club

查看第1个(下标为0的)数组元素:

[root@svr5 ~]# echo ${MY_SVRS[0]}
www
或者
[root@svr5 ~]# echo ${MY_SVRS}  			//省略下标时,默认视为0
www

输出下标为2的数组元素:

[root@svr5 ~]# echo ${MY_SVRS[2]}
mail

输出数组中下标从1开始的2个元素:

[root@svr5 ~]# echo ${MY_SVRS[@]:1:2}
ftp mail

查看数组的元素个数:

[root@svr5 ~]# echo ${#MY_SVRS[@]}
4
[root@svr5 ~]# echo ${#WEB_SVRS[@]}
4

步骤二:编写getips.sh脚本
1)任务需求及思路分析
使用read命令从键盘读入用户指定的IP地址,每次读入一个。
因为需要读多次,直到输入“EOF”时结束,所以可采用while循环结构,循环条件为输入的字符串不为“EOF”。
要求用数组保存每次输入的IP地址,那肯定从下标为0的元素开始存放,赋值操作放在循环体内,下标的递增通过一个变量i控制。
遇“EOF”结束while循环后,输出整个数组的内容,并显示数组元素的个数、第1个录入的IP地址。
2)根据实现思路编写脚本文件

[root@svr5 ~]# vim getips.sh
#!/bin/bash
IP=""  											//定义IP地址初值
i=0  												//控制下标增长的变量
while read -p "请添加IP地址(输EOF结束):" IP && [ "$IP" != "EOF" ]
do
    IPADDS[$i]="$IP"  							//每次录入赋值给不同的数组元素
    let i++
done
echo "您已录入的IP地址如下:"
echo ${IPADDS[@]}  								//输出整个数组
echo "总共包括 ${#IPADDS[@]} 个地址,"  				//报告数组元素的个数
echo "其中第1个IP地址是:${IPADDS[0]}"  			//输出第1个元素
[root@svr5 ~]# chmod +x getips.sh

3)验证、测试脚本

[root@svr5 ~]# ./getips.sh
请添加IP地址(输EOF结束):192.168.4.77
请添加IP地址(输EOF结束):172.16.16.220
请添加IP地址(输EOF结束):218.56.57.58
请添加IP地址(输EOF结束):192.168.1.5
请添加IP地址(输EOF结束):192.168.1.202
请添加IP地址(输EOF结束):220.106.0.20
请添加IP地址(输EOF结束):EOF
您已录入的IP地址如下:
192.168.4.77 172.16.16.220 218.56.57.58 192.168.1.5 192.168.1.202 220.106.0.20
总共包括 6 个地址,
其中第1个IP地址是:192.168.4.77

4)遍历数组元素时分行显示
当数组元素的内容较多时,直接输出 ${数组名[@]} 可能不方便查看,这种情况下可以利用循环遍历数组元素,通过连续取值的操作(或者 % 取模运算)限定每行只显示多少个IP地址(比如4个) 。
改进前面的getips.sh脚本,修改数组元素的输出方式,脚本内容参考如下:

[root@svr5 ~]# vim getips.sh
#!/bin/bash
IP=""
i=0
while read -p "请添加IP地址(输EOF结束):" IP && [ "$IP" != "EOF" ]
do
    IPADDS[$i]="$IP"
    let i++
done
echo "您已录入的IP地址如下:"
#echo ${IPADDS[@]}
i=0  											//控制下标增长的变量
while [ $i -lt ${#IPADDS[@]} ]  				//条件为下标小于元素个数
do
    echo ${IPADDS[@]:$i:4}  					//输出连续的四个元素
    let i+=4  									//下标自增4
done
echo "总共包括 ${#IPADDS[@]} 个地址,"
echo "其中第1个IP地址是:${IPADDS[0]}"
验证脚本执行效果:
[root@svr5 ~]# ./getips.sh
请添加IP地址(输EOF结束):192.168.4.77
请添加IP地址(输EOF结束):172.16.16.220
请添加IP地址(输EOF结束):192.168.1.5
请添加IP地址(输EOF结束):192.168.1.202
请添加IP地址(输EOF结束):10.0.0.17
请添加IP地址(输EOF结束):10.0.0.27
请添加IP地址(输EOF结束):220.106.0.20
请添加IP地址(输EOF结束):202.110.79.81
请添加IP地址(输EOF结束):61.133.84.128
请添加IP地址(输EOF结束):61.133.84.72
请添加IP地址(输EOF结束):EOF
您已录入的IP地址如下:
192.168.4.77 172.16.16.220 192.168.1.5 192.168.1.202
10.0.0.17 10.0.0.27 220.106.0.20 202.110.79.81
61.133.84.128 61.133.84.72
总共包括 10 个地址,
其中第1个IP地址是:192.168.4.77
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值