03-Shell 编程之循环语句与函数

目录

1.for 循环语句的结构

2.根据 IP 地址列表检查主机

3.使用 while 循环语句

4. until 循环语句

4.2until 语句应用示例

5.Shell 函数

5.1:两个数求和

5.2编写用户自定义函数

5.3函数变量的作用范围

递归函数

Shell 数组:


1.for 循环语句的结构

先创建一个文件叫 vim/root/users.txt //测试列表文件,再创建一个脚本 vim aaa.sh

#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
useradd $UNAME
echo "123456" | passwd --stdin $UNAME &>/dev/null
done
[root@localhost ~]# chmod +x uaddfor.sh
[root@localhost ~]# ./uaddfor.sh //测试并确认执行结果

使用 for 循环语句时,需要指定一个变量及可能的取值列表,针对每个不同的取值重复 执行相同的命令序列,直到变量值用完退出循环

2.根据 IP 地址列表检查主机

可先指定 IP 地址列表文件 ipadds.txt,然后编写一个名为 sss.sh 的 Shell 脚本,从 ipadds.txt 文件中读取各服务器的 IP 地址,重复执行 ping 连通性测试, 并根据测试结果输出相应的提示信息

#!/bin/bash
HLIST=$(cat /root/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
//-c 发送包的数量;-i 发送 ping 包间隔;-W 超时时间
if [ $? -eq 0 ]
then
echo "Host $IP is up." else
echo "Host $IP is down."
fi
done
[root@localhost ~]# chmod +x chkhosts.sh
[root@localhost ~]# ./chkhosts.sh //测试并确认执行结果

上述脚本代码中,do…done 循环体内嵌套使用了 if 条件选择语句,用来针对不同 IP 地址的测试结果进行判断,并输出相应的提示信息 在各种shell脚本语句都可以以嵌套使用的

3.使用 while 循环语句

for 循环语句非常适用于列表对象无规律,且列表来源已固定(如某个列表文件)的场 合

下面是语法结构:

while 条件测试操作
do
命令序列
done

1.批量添加规律编号的用户 在一些技术培训和学习领域,出于实验或测试的目的,需要批量添加用户账号,这些用 户的名称中包含固定的前缀字串,并按照数字顺序依次进行编号,账号的数量往往也是固定 的。例如,若要添加 20 个用户,名称依次为 stu1、stu2、…、stu20,可以参考以下操作下面是while语句的应用

[root@localhost ~]# vim uaddwhile.sh //批量添加用户的脚本
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 20 ]
do
useradd ${PREFIX}$i
echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null
let i++
done
[root@localhost ~]# chmod +x uaddwhile.s

若要删除 uaddwhile.sh 脚本所添加的用户,只需参考上述脚本代码,将 while 循环体 中添加用户的命令序列改为删除用户的操作即可

4. until 循环语句

until 循环与 while 循环类似,while 循环能实现的脚本 until 同样也可以实现,但区别是 while 循环在条件为真是继续执行循环,而 until 则是在条件为假时执行循环

4.2until 语句应用示例

1.计算 1~50 的和:计算从 1 到 50 的和,从 1 开始相加,采用循环的方式,每次循环后加 1,将得到的值加 入计算的和中,数字运算采用的是 let 方式,直到加到 50 为止,具体参考如下

[root@localhost ~]# vim sum1to50_until_v1.sh
#!/bin/bash
i=0;s=0
until [ $i -eq 50 ]
do
let "i=$i+1";let "s=$s+$i" done
echo 'sum(1..50)='$s
[root@localhost ~]# chmod +x sum1to50_until_v1.sh
[root@localhost ~]# ./sum1to50_until_v1.sh
sum(1..50)=1275

5.Shell 函数

将一些相对独立的代码变成函数,可以 提高程序可读性与重用性,避免编写大量重复代码

1.“function”关键字表示定义一个函数,可以省略

2.“{”符号表示函数执行命令的入口,该符号可以与函数名同行也可以在函数名下一行 的句首;

3.“}”符号表示函数体结束,两个大括号之间{ }是函数

4.“命令序列”部分可以是任意的 Shell 命令,也可以调用

5.“return”表示退出函数返回一个退出值,通过返回值判断执行是否成功,也可以使 用 exit 终止整个 Shell

5.1:两个数求和

使用 Shell 脚本实现两个数相加求和,通过定义函数的方式来完成。sum 函数内部通过 read 命令接收用户分别输入的两个数,然后做加法运算,最后通过调用函数的方式来输出 两个数的和

[root@localhost ~]# vim sum.sh
#!/bin/bash
sum(){
read -p "请输入第一个数:" NUM1
read -p "请输入第二个数:" NUM2
echo “你输入的两个数为: $NUM1 和$NUM2.” SUM=$(( NUM1+$NUM2))
echo “两个数的和为: $SUM”
}
sum
[root@localhost ~]# chmod +x sum.sh
[root@localhost ~]# ./sum.sh
请输入第一个数:2
请输入第二个数:3
“你输入的两个数为: 2 和 3.”
“两个数的和为: 5”

5.2编写用户自定义函数

CentOS 系统由 6 版本升级到 7 版本之后,其启动服务的方式发生了很大变化。在生产 环境中还有很大一部分的企业在使用 6 系列,为了兼容 6 和 7,要求写一函数自动判断系统 型号,根据型号执行对应的服务管理程序,并且设置开机生效

[root@localhost ~]# vim function
servicectl_usage () {
echo "Usage:servicectl <service-name> <start|stop|restart|reload|status>"
return 1
}
chk_centos_ver () {
grep "CentOS.*release 7." /etc/centos-release &> /dev/null && echo "7" grep "CentOS.*release 6." /etc/centos-release &> /dev/null && echo "6" grep "CentOS.*release 5." /etc/centos-release &> /dev/null && echo "5"
}
servicectl () {
[[ -z $1 || -z $2 ]] && servicectl_usage
[ $(chk_centos_ver)=="7" ] && systemctl $2 ${1}.service || service $1 $2
}
[root@localhost ~]# chmod +x function
[root@localhost ~]# source function
[root@localhost ~]# echo 'source /root/function' >> ~/.bashrc
[root@localhost ~]# servicectl vsftpd status ● vsftpd.service - Vsftpd ftp daemon
Loaded: loaded (/usr/lib/systemd/system/vsftpd.service; disabled; vendor preset: disabled)
Active: active (running) since Thu 2019-11-14 13:49:55 CST; 42s ago
Process: 2369 ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf (code=exited, status=0/SUCCESS)
Main PID: 2370 (vsftpd)
CGroup: /system.slice/vsftpd.service
└─2370 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
Nov 14 13:49:55 virgon systemd[1]: Starting Vsftpd ftp daemon... Nov 14 13:49:55 virgon systemd[1]: Started Vsftpd ftp daemon.

上图的可以不看

5.3函数变量的作用范围

函 数内部变量的使用,可以避免函数内外同时出现同名变量对脚本结果的影响。local 命令的 使用如下所示

[root@localhost ~]# vim fun_scope.sh
myfun ()
{
local i
i=8
echo $i
}
i=9
myfun
echo $i
[root@localhost ~]# chmod +x fun_scope.sh
[root@localhost ~]# ./fun_scope.sh
8
9

myfun 函数内部使用了 local 命令设置变量 i,其作用是将变量 i 限定在函 数内部。myfun 函数外部同样定义了变量 i,内部变量 i 和全局变量 i 互不影响。脚本执行时 先调用了函数 myfun,函数内部变量 i 为 8,所以输出结果是 8。调用完函数之后,给变量 i 赋值为 9,再打印外部变量 i,所以又输出9

递归函数

Shell 也可以实现递归函数,就是可以调用自己本身的函数

[root@localhost ~]# # vim fun_recursion.sh
function list_files()
{
for f in `ls $1`;
do
if [ -d "$1/$f" ]; then
echo "$2$f"
list_files "$1/$f" " $2" else
echo "$2$f"
fi
done
}
list_files "/var/log" ""
[root@localhost ~]# chmod +x fun_recursion.sh
[root@localhost ~]# ./fun_recursion

Shell 数组:

。Shell 中的数组与 Java、 C、Python 不同,只有一维数组,没有二维数组。数组元素的大小与限制,也不需要事先 定义。Shell 数组用括号()来表示,元素用空格分隔,元素的下标与大部分编程语言类似 从 0 开始

数组常用定义方法包括以下几种。 方法一: 数组名=(value0 value1 value2 ...)

方法二: 数组名=([0]=value [1]=value [2]=value ...)

方法三: 列表名=”value0 value1 value2 ...” 数组名=($列表名)

方法四: 数组名[0]=”value” 数组名[1]=”value” 数组名[2]=”valu

(1)获取数组长度

[root@localhost ~]# arr_number=(1 2 3 4 5)
[root@localhost ~]# arr_length=${#arr_number[*]}
[root@localhost ~]# echo $arr_length
5
[root@localhost ~]# arr_length_1=${#arr_number[@]}
[root@localhost ~]# echo $arr_length_1
5

(2)读取某下标赋值

[root@localhost ~]# arr_index2=${arr_number[2]} //第三个元素
[root@localhost ~]# echo $arr_index2
3

(3)数组遍历

[root@localhost ~]# vim array_traverse.sh
#!/bin/bash
arr_number=(1 2 3 4 5)
for v in ${arr_number[@]}
do
echo $v
done
[root@localhost ~]# chmod +x array_traverse.sh
[root@localhost ~]# ./array_traverse.sh
1
2
3
4
5

(4)数组切片

[root@centos-7 ~]# arr=(1 2 3 4 5)
[root@centos-7 ~]# echo ${arr[@]} //输出整个数组
1 2 3 4 5
[root@centos-7 ~]# echo ${arr[@]:0:2} //${数组名[@或*]:起始位置:长度}
1 2
[root@centos-7 ~]# echo ${arr[@]:2:3}
3 4 

(5)数组替换

[root@centos-7 ~]# arr=(1 2 3 4 5)
[root@centos-7 ~]# echo ${arr[@]/4/66} //${数组名[@或*]/查找字符/替换字符}
1 2 3 66 5
[root@centos-7 ~]# echo ${arr[@]} //并不会替换数组原有内容
1 2 3 4 5
[root@centos-7 ~]# arr=(${arr[@]/4/66}) //要实现改变原有数组,可通过重新赋值实现
[root@centos-7 ~]# echo ${arr[@]}
1 2 3 66 

  • 29
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值