当前位置 : 主页 > 操作系统 > centos >

Linux 云计算集群架构师->第二十一章 结构化命令 case 和 for、while 循环

来源:互联网 收集:自由互联 发布时间:2022-09-29
第二十一章 结构化命令 case 和 for、while 循环 (上课时间2021-07-17,笔记整理时间2021-07-26) 本节所讲内容: 21.1 case-流程控制语句 21.2 循环语句 21.3 while 循环语句和循环嵌套 21.4 实战-3 个

第二十一章 结构化命令 case 和 for、while 循环

(上课时间2021-07-17,笔记整理时间2021-07-26)

本节所讲内容:

21.1 case-流程控制语句

21.2 循环语句

21.3 while 循环语句和循环嵌套

21.4 实战-3 个 shell 脚本实战

21.1 流程控制语句:case

控制语句:用来实现对程序流程的选择、循环、转向和返回等进行控制。case 是开关语句的一个组成部分;

它是根据变量的不同进行取值比较,然后针对不同的取值分别执行不同的命令操作

适用于多分支,是一个多选择语句

case 变量或表达式 in

​ 变量或表达式 1)

​ 命令序列 1

​ ;;

​ 变量或表达式 2)

​ 命令序列 2

​ ;;

​ ……

​ *)

​ 默认命令序列

esac

case 语句执行流程控制:

image-20210725115154043

执行流程:

首先使用“变量或表达式”的值与值 1 进行比较,若取值相同则执行值 1 后的命令序列,直到遇见双分号“;; ”后跳转至 esac,表示分支结束;

若与值 1 不相匹配,则继续与值 2 进行比较,若取值相同则执行值 2 后的命令序列,直到遇见双分号“;; ”后跳转至 esac,表示结束分支。

依次类推,若找不到任何匹配的值,则执行默认模式“ *) ”后的命令序列,直到遇见 esac 后结束分支

注意事项:

“变量或表达式”后面必须为单词 in,每一个“变量或表达式”的值必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;

匹配中的值可以是多个值,通过“|”来分隔

编写一个操作文件的脚本

[root@CentOS83 ~]# vim case.sh [root@CentOS83 ~]# cat case.sh #################################################################### #File Namme: case-1.sh # Author: xuegod #################################################################### #!/bin/bash cat <<eof **************** ** 1. backup ** ** 2. copy ** ** 3. quit ** **************** eof read -p "请输入您的选择: " OP case $OP in 1|backup) echo "BACKUP......" ;; 2|copy) echo "COPY....." ;; 3|quit) exit ;; *) echo error esac [root@CentOS83 ~]# bash case.sh **************** ** 1. backup ** ** 2. copy ** ** 3. quit ** **************** 请输入您的选择: 1 BACKUP......

编写一个启动 apache 服务脚本

[root@CentOS83 ~]# vim case1.sh [root@CentOS83 ~]# cat case1.sh #!/bin/bash case $1 in start) /usr/bin/systemctl $1 httpd /usr/bin/ps aux | grep httpd | grep -v grep echo "httpd start" ;; stop) /usr/bin/systemctl $1 httpd /usr/bin/ps aux | grep httpd | grep -v grep echo "httpd stop" ;; restart) /usr/bin/systemctl $1 httpd /usr/bin/ps aux | grep httpd | grep -v grep echo "httpd restart" ;; status) /usr/bin/systemctl $1 httpd | grep -v grep ;; *) echo "please input | start | stop | restart | status |" esac [root@CentOS83 ~]# sh case1.sh status

21.2 循环语句

21.2.1 for-do-done

1、语法格式:

for var in list ###:for 后跟 var(var 相当于一个变量)list(相当于一个列表)

do

​ commands

done

或:

for var in list ; do

​ commands

done

image-20210725131629784

2、取值列表有多种取值方式,比如可以直接读取 in 后面的值,默认以空格做分隔

[root@CentOS83 ~]# vim for-1.sh [root@CentOS83 ~]# cat vim for-1.sh cat: vim: No such file or directory #!/bin/bash for var in a1 b1 c1 d1 do echo the text is var done [root@CentOS83 ~]# sh for-1.sh the text is var the text is var the text is var the text is var

2、列表中的复杂值,可以使用引号或转义字符”\”来加以约束

[root@CentOS83 ~]# vim for-2.sh [root@CentOS83 ~]# cat for-2.sh #!/bin/bash for var in a1 b1 'c1 d1' e2 'hello word' do echo the text is $var done [root@CentOS83 ~]# bash for-2.sh the text is a1 the text is b1 the text is c1 d1 the text is e2 the text is hello word [root@CentOS83 ~]# vim for-3.sh [root@CentOS83 ~]# cat for-3.sh #!/bin/bash for var in a1 b\'1 'c1 d1' e2 'hello world' do echo the text is $var done [root@CentOS83 ~]# bash for-3.sh the text is a1 the text is b'1 the text is c1 d1 the text is e2 the text is hello world

4、从命令中取值

[root@CentOS83 ~]# vim for-4.sh [root@CentOS83 ~]# cat for-4.sh #默认以以空格做分隔符 #!/bin/bash for i in `cat /etc/hosts` do echo "$i" done [root@CentOS83 ~]# sh for-4.sh 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

5、自定义 shell 分隔符

默认情况下,base shell 会以空格、制表符、换行符做为分隔符。通过 IFS 来自定义为分隔符指定单个字符做分隔符:

IFS=: #以:冒号做分隔符

可以指定多个

如 IFS='\n: "; ' #这个赋值会将反斜杠、n、冒号、双引号、分号作为字段分隔符。

注:$'\n'与'\n'时的区别

IFS='\n' #将字符\和字符 n 作为字段分隔符。

IFS=$'\n' #使用换行符做为字段分隔符。

[root@CentOS83 ~]# vim for-6.sh #指定以\n 回车做为 for 语句的分隔符 [root@CentOS83 ~]# cat for-6.sh #!/bin/bash IFS=$'\n' #IFS=: #以:冒号做分隔符 for i in `cat /etc/hosts` do echo "$i" done [root@CentOS83 ~]# sh for-6.sh 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6

6、C 语言风格的 for

语法格式:

for ((i=0;i<10;i++))

do

​ commmands

done

单个变量 输出 1 到 10 之间的数字

[root@CentOS83 ~]# vim for-7.sh [root@CentOS83 ~]# cat for-7.sh #!/bin/bash for (( i-1 ; i<=10 ; i++ )) #i=1 只赋值一次。然后执行 i <= 10 do echo num is $i # i++在这里执行。 当 for 循环体中所有命令执行完后,再执行 i++ done [root@CentOS83 ~]# sh for-7.sh num is num is 1 num is 2 num is 3 num is 4 num is 5 num is 6 num is 7 num is 8 num is 9 num is 10

多个变量, 同时输出 1-9 的升序和降序

[root@CentOS83 ~]# vim for-9.sh [root@CentOS83 ~]# cat for-9.sh #!/bin/bash for (( a=1,b=9 ; a<10 ; a++,b-- )) do echo num is $a - $b done [root@CentOS83 ~]# sh for-9.sh num is 1 - 9 num is 2 - 8 num is 3 - 7 num is 4 - 6 num is 5 - 5 num is 6 - 4 num is 7 - 3 num is 8 - 2 num is 9 - 1 [root@CentOS83 ~]# vim for-9.sh [root@CentOS83 ~]# cat for-9.sh #!/bin/bash for (( a=1,b=9 ; a<10,b>5; a++,b-- )) do echo num is $a - $b done [root@CentOS83 ~]# sh for-9.sh num is 1 - 9 num is 2 - 8 num is 3 - 7 num is 4 - 6

21.3 while 循环语句和循环嵌套

21.3.1 while-do-done

重复测试指令的条件,只要条件成立就反复执行对应的命令操作,直到命令不成立或为假;

语法格式如下:

while 测试命令

do

命令

done

image-20210726102151501

注意:避免陷入死循环 while true

降序输出 10 到 1 的数字

[root@CentOS83 ~]# vim while1.sh [root@CentOS83 ~]# cat while1.sh #!/bin/bash var=10 while [ $var -ge 0 ] do echo $var var=$[$var-1] #var=$((var-1)) #let var-- done [root@CentOS83 ~]# sh while1.sh 10 9 8 7 6 5 4 3 2 1 0 #自增操作 let var++ #自减操作 let var-- [root@CentOS83 ~]# vim while2.sh [root@CentOS83 ~]# cat while2.sh #!/bin/bas num=1 while [ $num -lt 10 ] do sum=$(( $num * $num )) echo "$num * $num = $sum" ((num++)) # let num++ done [root@CentOS83 ~]# sh while2.sh 1 * 1 = 1 2 * 2 = 4 3 * 3 = 9 4 * 4 = 16 5 * 5 = 25 6 * 6 = 36 7 * 7 = 49 8 * 8 = 64 9 * 9 = 81

21.3.2 嵌套循环

例 1:批量添加 a.txt 文件 5 个用户

[root@CentOS83 ~]# vim user.txt #添加 5 个用户 [root@CentOS83 ~]# cat user.txt which cd ls df rm

编写脚本的思路

1 明确脚本的功能

2 编写脚本时会使用到那些命令 ? useradd passwd for

3 把变化的数据使用变量表示

4 选择适合的流程控制 (选择 、 循环 、分支)

[root@CentOS83 ~]# vim adduser.sh [root@CentOS83 ~]# cat adduser.sh #!/bin/bash for name in `cat/root/user.txt` #for name in $(cat /root/user.txt) do id $name &> /dev/null if [$? -ne 0 ];then useradd $name echo "password" | passwd --stdin $name &> /dev/null echo "user $name create" else echo "user $name is exits" fi done [root@CentOS83 ~]# sh adduser.sh user which create user cd create user ls create user df create user rm create [root@CentOS83 ~]# tail -n 5 /etc/shadow #查看最后5行 which:$6$G909SdgSWDO/zYbw$h8LJDbraCyDtOd4TFzNa.mkSCD/Xmah.J0kS85fwuJsPoYuNUDInox9bDy3QVGNh8bkvKgJHreRtJTQOWOnah.:18834:0:99999:7::: cd:$6$bW4YMSXRt1ilJVzm$swNCKYBwWJMUgtJ36stlvY1Sx9JpgSQyo4kZHi0lxuHSb0d2zrbk456/EV6ZbJOOqE4THiZ4c45RJxBBoz5VV1:18834:0:99999:7::: ls:$6$8wqPZT.TNJb.ClSj$Cd.xY2NCs31YSbRnJKLleoHBKoWIDpH0MngrPSU/XIySzBLN/m.qDcjROHRPR/DXPQIdKZRMv2y/5XlcHdLLz/:18834:0:99999:7::: df:$6$HoS6AF1r/ZWeu9Qi$p/6APXsbbTPGcvwgJxwFdK.4y5LvU3i2HHRK9h4SUXilwIUASgtpj/YlSwHAv2OwZhKHR0wQ7V6hhRfI7KSwF1:18834:0:99999:7::: rm:$6$PURFT3X3E1FtvE.W$ft1OpXzpJTSTtnusNxlKquUmBmMC2pCK8atcDbENLtOjT9ro0YkeSd94ROp.zi728Q4qZUBFmXmxdq3yE.4qt0:18834:0:99999:7:::

注:&> 是正确和错误的信息都重定向到/dev/null 里面,相当于 1> /dev/null 2>&1 这个写法

打印九九乘法表

[root@CentOS83 ~]# vim forfor.sh [root@CentOS83 ~]# cat forfor.sh #!/bin/bash for i in `seq 9` do for j in `seq $i` do echo -n "$i*$j=`echo $(($i*$j))` " done echo " " done [root@CentOS83 ~]# sh forfor.sh 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

注:外层循环循环行,内层循环循环列

规律: 内层循环的变量<=外层循环的变量

echo -n 代表不换行

21.4 实战-3 个 shell 脚本实战

21.4.1 实战-将/opt 目录下所有的日志文件全自动打包

[root@CentOS83 ~]# vim log-back.sh [root@CentOS83 ~]# cat log-back.sh #!/bin/bash SRC_DIR=/var/log/ DES_DIR=/opt/backup/`date +%Y%m%d` #如果目标目录不存在,则创建目标目录 if [ ! -d $DES_DIR ] ; then mkdir -p $DES_DIR fi #遍历找到的日志文件并打包 for i in `find $SRC_DIR -name "*.log"` do tar czf $i.gz $i &> /dev/null done #剪切打包的日志文件到目标目录 mv /var/log/*.gz $DES_DIR ls -lh $DSC_DIR echo "The scripts exec end,Files tar successfully!"

21.4.2 找出 10.170.80.1-10 网段中,服务器已经关机的 IP 地址

[root@CentOS83 ~]# vim ping.sh [root@CentOS83 ~]# cat ping.sh #!/bin/bash i=1 for (( i=1;i<=10;i++ )) # for I in {1..10} # for I in `seq 10` do ping -c 3 10.170.80.$i &> /dev/null if [ $? -ne 0 ];then echo 10.170.80.$i is shutdown fi done [root@CentOS83 ~]# sh ping.sh

21.4.3 批量创建帐号并生成随机密码

[root@CentOS83 ~]# vim useradd.sh [root@CentOS83 ~]# cat useradd.sh #!/bin/bash for i in lsuser{1..10} do useradd $i if [ $? -eq 0 ];then echo "create ${i} user is successfully!" else echo "create ${i} user is failed!" fi pass=`date +%s|md5sum|cut -c 1-8` sleep 1 echo "$i:$pass" >> /tmp/passwd.log echo $pass |passwd --stdin $i &> /dev/null if [ $? -eq 0 ];then echo " ${i} user change passwd is successfully!" else echo " ${i} user change passwd is failed!" fi done [root@CentOS83 ~]# sh useradd.sh create lsuser1 user is successfully! lsuser1 user change passwd is successfully! …………………… [root@CentOS83 ~]# cat /tmp/passwd.log lsuser1:709f2450 lsuser2:b556b6af lsuser3:7d27d5e9 lsuser4:d9aab737 lsuser5:7453d2fb lsuser6:7aaecc2d lsuser7:489905d6 lsuser8:2c100a10 lsuser9:22700f54 lsuser10:acdfdfc7

注意:%s 总秒数。起算时间为 1970-01-01 00:00:00 UTC

总结:

21.1 case - 流程控制语句

21.2 for 循环语句

21.3 while 循环语句和循环嵌套

21.4 实战-3 个 shell 脚本实战

网友评论