学习笔记:CentOS7学习之二十二: 结构化命令case和for、while循环
本文用于记录学习体会、心得,兼做笔记使用,方便以后复习总结。内容基本完全参考学神教育教材,图片大多取材自学神教育资料,在此非常感谢MK老师和学神教育的优质教学。希望各位因学习需求而要进行转载时,能申明出处为学神教育,谢谢各位!
22.1 流程控制语句:case
控制语句:用来实现对程序流程的选择、循环、转向和返回等进行控制。case是开关语句的一个组成部分;
它是根据变量的不同进行取值比较,然后针对不同的取值分别执行不同的命令操作
适用于多分支,是一个多选择语句
case 变量或表达式 in
变量或表达式1)
命令序列1
;;
变量或表达式2)
命令序列2
;;
……
*)
默认命令序列
esac
case语句执行流程控制:
执行流程:
首先使用“变量或表达式”的值与值1进行比较,若取值相同则执行值1后的命令序列,直到遇见双分号“;; ”后跳转至esac,表示分支结束;
若与值1不相匹配,则继续与值2 进行比较,若取值相同则执行值2 后的命令序列,直到遇见双分号“;; ”后跳转至esac,表示结束分支。
依次类推,若找不到任何匹配的值,则执行默认模式“ *) ”后的命令序列,直到遇见esac后结束分支
注意事项:
- “变量或表达式”后面必须为单词in,每一个“变量或表达式”的值必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;
- 匹配中的值可以是多个值,通过“|”来分隔
例1:编写一个操作文件的脚本
[root@CentOs7_64_1_128 tmp]# vim case1.sh
#!/bin/bash
cat << eof
**************
** 1.backup **
** 2.copy **
** 3.quit **
**************
eof
read -p "input your choice:" op
case $op in
1|backup)
echo "Backup......"
;;
2|copy)
echo "Copy......"
;;
3|quit)
exit 10
;;
*)
echo error
[root@CentOs7_64_1_128 tmp]# bash case1.sh
**************
** 1.backup **
** 2.copy **
** 3.quit **
**************
input your choice:1
Backup......
[root@CentOs7_64_1_128 tmp]# bash case1.sh
**************
** 1.backup **
** 2.copy **
** 3.quit **
**************
input your choice:2
Copy......
[root@CentOs7_64_1_128 tmp]# bash case1.sh
**************
** 1.backup **
** 2.copy **
** 3.quit **
**************
input your choice:3
[root@CentOs7_64_1_128 tmp]# bash case1.sh
**************
** 1.backup **
** 2.copy **
** 3.quit **
**************
input your choice:5
error
例2:编写一个启动apache的脚本
[root@CentOs7_64_1_128 tmp]# vim case2.sh
#!/bin/bash
case $1 in
start)
systemctl $1 httpd
ps -aux|grep httpd
echo "httpd started"
;;
stop)
systemctl $1 httpd
ps -aux|grep httpd
echo "httpd stoped"
;;
status)
systemctl $1 httpd
;;
restart)
systemctl $1 httpd
ps -aux|grep httpd
echo "httpd restarted"
;;
*)
echo "USAGE:$0 start|stop|status|restart"
esac
[root@CentOs7_64_1_128 tmp]# bash case2.sh
USAGE:case2.sh start|stop|status|restart
[root@CentOs7_64_1_128 tmp]# bash case2.sh start
root 16077 0.0 1.4 415036 58252 ? Ssl 14:45 0:01 /usr/sbin/httpd -DFOREGROUND
apache 16081 0.0 0.4 431248 16728 ? S 14:45 0:00 /usr/sbin/httpd -DFOREGROUND
apache 16083 0.0 0.4 431248 16728 ? S 14:45 0:00 /usr/sbin/httpd -DFOREGROUND
apache 16084 0.0 0.4 431248 16728 ? S 14:45 0:00 /usr/sbin/httpd -DFOREGROUND
apache 16085 0.0 0.4 431248 16728 ? S 14:45 0:00 /usr/sbin/httpd -DFOREGROUND
apache 16086 0.0 0.4 431248 16728 ? S 14:45 0:00 /usr/sbin/httpd -DFOREGROUND
root 18406 0.0 0.0 112724 972 pts/0 R+ 17:03 0:00 grep httpd
httpd started
[root@CentOs7_64_1_128 tmp]# vim case2.sh
[root@CentOs7_64_1_128 tmp]# bash case2.sh restart
root 18434 53.0 1.4 415036 58244 ? Ssl 17:04 0:00 /usr/sbin/httpd -DFOREGROUND
apache 18438 0.0 0.3 428780 12560 ? R 17:04 0:00 /usr/sbin/httpd -DFOREGROUND
apache 18439 0.0 0.3 428780 12560 ? R 17:04 0:00 /usr/sbin/httpd -DFOREGROUND
apache 18440 0.0 0.3 428780 12560 ? R 17:04 0:00 /usr/sbin/httpd -DFOREGROUND
apache 18441 0.0 0.3 428780 12560 ? R 17:04 0:00 /usr/sbin/httpd -DFOREGROUND
apache 18442 0.0 0.3 428780 12560 ? R 17:04 0:00 /usr/sbin/httpd -DFOREGROUND
root 18444 0.0 0.0 112724 972 pts/0 R+ 17:04 0:00 grep httpd
22.2 循环语句
22.1.2 for-do-done
for var in list
do
commands
done
或:
for var in list ; do
commands
done
取值列表有多种取值方式,比如
1、可以直接读取in 后面的值,默认以空格做分隔
[root@CentOs7_64_1_128 tmp]# vim for1.sh
#!/bin/bash
for var in a1 b1 c1 d1
do
echo "the text is $var"
done
[root@CentOs7_64_1_128 tmp]# bash for1.sh
the text is a1
the text is b1
the text is c1
the text is d1
2、列表中的复杂值,可以使用 引号或转义字符”/”来加以约束
[root@CentOs7_64_1_128 tmp]# vim for2.sh
#!/bin/bash
for i in a1 b1 "c1 d1" e2 "hello world"
do
echo "the text is $i"
done
[root@CentOs7_64_1_128 tmp]# bash for2.sh
the text is a1
the text is b1
the text is c1 d1
the text is e2
the text is hello world
[root@CentOs7_64_1_128 tmp]# vim for3.sh
#!/bin/bash
for var in a1 b\'1 "c1 d1" e2 "hello world" I\'s a22
do
echo "the text is $var"
done
~
[root@CentOs7_64_1_128 tmp]# bash for3.sh
the text is a1
the text is b'1
the text is c1 d1
the text is e2
the text is hello world
the text is I's
the text is a22
3、从变量中取值
[root@CentOs7_64_1_128 tmp]# vim for4.sh
#!/bin/bash
list="a1 b1 c1 d1"
for i in $list
do
echo "is a $i"
done
[root@CentOs7_64_1_128 tmp]# bash for4.sh
is a a1
is a b1
is a c1
is a d1
4、从命令中取值
[root@CentOs7_64_1_128 tmp]# vim for5.sh #默认以空格为分隔符
#!/bin/bash
for i in `cat /etc/hosts`
do
echo "$i"
done
[root@CentOs7_64_1_128 tmp]# bash for5.sh
127.0.0.1
localhost
localhost.localdomain
localhost4
localhost4.localdomain4
::1
localhost
localhost.localdomain
localhost6
localhost6.localdomain6
192.168.87.128
CentOs7_64_1_128
5、自定义shell分隔符
默认情况下,base shell会以空格、制表符、换行符做为分隔符。通过IFS来自定义为分隔符
指定单个字符做分隔符:
IFS=: #以:冒号做分隔符
可以指定多个
如 IFS='\n':;" #这个赋值会将反斜杠、n、冒号、分号和双引号作为字段分隔符。
注:$'\n'与'\n'时的区别
IFS='\n' #将字符\和字符n作为IFS的换行符。
IFS=$'\n' #正真的使用换行符做为字段分隔符。
[root@CentOs7_64_1_128 tmp]# vim for6.sh # 指定以\n回车做为 for语句的分隔符
#!/bin/bash
IFS=$'\n'
for i in `cat /etc/hosts`
do
echo "$i"
done
[root@CentOs7_64_1_128 tmp]# bash for6.sh
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.87.128 CentOs7_64_1_128
[root@CentOs7_64_1_128 tmp]# vim for7.sh # 以:冒号做分隔符
#!/bin/bash
IFS=:
list=`head -1 /etc/passwd`
for i in $list
do
echo "$i"
done
[root@CentOs7_64_1_128 tmp]# bash for7.sh
root
x
0
0
root
/root
/bin/bash
6、C语言风格的for
语法格式:
for ((i=0;i<10;i++))
do
commmands
done
例1:单个变量。 输出1到10之间的数字
[root@CentOs7_64_1_128 tmp]# vim for8.sh
#!/bin/bash
for ((i=1;i<=10;i++))
do
echo "number is $i"
done
[root@CentOs7_64_1_128 tmp]# bash for8.sh
number is 1
number is 2
number is 3
number is 4
number is 5
number is 6
number is 7
number is 8
number is 9
number is 10
例2:多个变量。 同时输出1-9的升序和降序
[root@CentOs7_64_1_128 tmp]# vim for9.sh
#!/bin/sh
for((a=1,b=10;a<=10;a++,b--))
do
echo "a = $a, b = $b"
done
[root@CentOs7_64_1_128 tmp]# bash for9.sh
a = 1, b = 10
a = 2, b = 9
a = 3, b = 8
a = 4, b = 7
a = 5, b = 6
a = 6, b = 5
a = 7, b = 4
a = 8, b = 3
a = 9, b = 2
a = 10, b = 1
22.3 while循环语句和循环嵌套
22.3.1 while-do-done
重复测试指令的条件,只要条件成立就反复执行对应的命令操作,直到命令不成立或为假;
语法格式如下:
while 测试命令
do
命令
done
注意:避免陷入死循环 while true
例1:降序输出10到1的数字
[root@CentOs7_64_1_128 tmp]# vim while1.sh
#!/bin/bash
var=10
while [ $var -gt 0 ]
do
echo $var
((var--))
done
[root@CentOs7_64_1_128 tmp]# bash while1.sh
10
9
8
7
6
5
4
3
2
1
例2:输出如下图两数相乘的效果
自增操作 let var++
自减操作 let var--
[root@CentOs7_64_1_128 tmp]# vim while2.sh
#!/bin/bash
var=1
while [ $var -lt 10 ]
do
echo " $var * $var = $(($var*$var))"
let var++
done
[root@CentOs7_64_1_128 tmp]# bash 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
22.3.2 嵌套循环
例1:批量添加a.txt文件5个用户
[root@CentOs7_64_1_128 tmp]# vim adduser.sh # 批量添加添加用户名
#!/bin/bash
IFS=$'\n' # 设置换行符\n作为分隔符
i=`cat /tmp/a.txt` # 设置i为a.txt中用户名
for name in $i
do
id $name &> /dev/null #查看用户名是否已经存在
if [ $? -ne 0 ]; then #如果不存在,则添加用户,给用户添加密码
useradd $name
echo "123456" |passwd --stdin $name &> /dev/null
echo "user $name created"
else
echo "user $name is exist"
fi
done
[root@CentOs7_64_1_128 tmp]# bash adduser.sh
正在创建信箱文件: 文件已存在
user yangjie1 created
正在创建信箱文件: 文件已存在
user yangjie2 created
正在创建信箱文件: 文件已存在
user yangjie3 created
正在创建信箱文件: 文件已存在
user yangjie4 created
正在创建信箱文件: 文件已存在
user yangjie5 created
[root@CentOs7_64_1_128 tmp]# vim deluser.sh #批量删除用户名
#!/bin/bash
IFS=$'\n'
i=`cat /tmp/a.txt`
for name in $i
do
id $name &> /dev/null
if [ $? -eq 0 ]; then
userdel $name
rm -rf /home/$name
echo "user $name delete sucessful"
else
echo "user $name does not exist"
fi
done
[root@CentOs7_64_1_128 tmp]# bash deluser.sh
user yangjie1 delete sucessful
user yangjie2 delete sucessful
user yangjie3 delete sucessful
user yangjie4 delete sucessful
user yangjie5 delete sucessful
注:&> 是正确和错误的信息都重定向到/dev/null里面
例2 :打印九九乘法表
注:外层循环循环行,内层循环循环列
规律: 内层循环的变量<=外层循环的变量
[root@centos-7-24 tmp]# vim for-for.sh
#!/bin/bash
for i in $(seq 9)
do
for j in $(seq $i)
do
echo -n "$i * $j = $(($i*$j)) " # -n不换行
done
echo " "
done
[root@centos-7-24 tmp]# bash for-for.sh
22.4 实战-2个shell脚本实战
22.4.1 实战-将/var目录下所有的日志文件全自动打包,存放到opt下以日期命名的文件夹中备份
[root@centos-7-24 tmp]# vim optback.sh
#!/bin/bash
srcdir="/var/log"
desdir="/opt/backup/`date +"%Y%m%d"`"
if [ ! -d $desdir ]; then
mkdir -p $desdir
fi
for i in `find $srcdir -name "*.log"`
do
tar -czvf $i.tar.gz $i
mv $i.tar.gz $desdir
done
[root@centos-7-24 tmp]# bash optback.sh
[root@centos-7-24 tmp]# ll /opt/backup/20190702/
总用量 552
-rw-r--r--. 1 root root 135 7月 2 22:51 :0-greeter.log.tar.gz
-rw-r--r--. 1 root root 4264 7月 2 22:51 :0.log.tar.gz
-rw-r--r--. 1 root root 5975 7月 2 22:51 anaconda.log.tar.gz
-rw-r--r--. 1 root root 92212 7月 2 22:51 audit.log.tar.gz
-rw-r--r--. 1 root root 10704 7月 2 22:51 boot.log.tar.gz
-rw-r--r--. 1 root root 1332 7月 2 22:51 ifcfg.log.tar.gz
-rw-r--r--. 1 root root 245327 7月 2 22:51 journal.log.tar.gz
-rw-r--r--. 1 root root 140 7月 2 22:51 ks-script-lByocF.log.tar.gz
-rw-r--r--. 1 root root 141 7月 2 22:51 ks-script-M7ywwD.log.tar.gz
-rw-r--r--. 1 root root 128 7月 2 22:51 mariadb.log.tar.gz
-rw-r--r--. 1 root root 83266 7月 2 22:51 packaging.log.tar.gz
-rw-r--r--. 1 root root 6253 7月 2 22:51 program.log.tar.gz
-rw-r--r--. 1 root root 12484 7月 2 22:51 storage.log.tar.gz
-rw-r--r--. 1 root root 1759 7月 2 22:51 tuned.log.tar.gz
-rw-r--r--. 1 root root 385 7月 2 22:51 vmware-network.1.log.tar.gz
-rw-r--r--. 1 root root 385 7月 2 22:51 vmware-network.2.log.tar.gz
-rw-r--r--. 1 root root 391 7月 2 22:51 vmware-network.3.log.tar.gz
-rw-r--r--. 1 root root 383 7月 2 22:51 vmware-network.log.tar.gz
-rw-r--r--. 1 root root 2778 7月 2 22:51 vmware-vmsvc.log.tar.gz
-rw-r--r--. 1 root root 167 7月 2 22:51 wpa_supplicant.log.tar.gz
-rw-r--r--. 1 root root 4786 7月 2 22:51 X.log.tar.gz
-rw-r--r--. 1 root root 5543 7月 2 22:51 Xorg.0.log.tar.gz
-rw-r--r--. 1 root root 4771 7月 2 22:51 Xorg.9.log.tar.gz
-rw-r--r--. 1 root root 10788 7月 2 22:51 yum.log.tar.gz
22.4.2 实战-找出192.168.234.20-30网段中,服务器已经关机的IP地址
[root@centos-7-24 tmp]# vim ping.sh
#!/bin/bash
for((i=20;i<=30;i++))
do
ping -c 3 192.168.234.$i &> /dev/null
if [ $? -ne 0 ]; then
echo "192.168.234.$i is shutdown"
else
echo "192.168.234.$i is running"
fi
done
[root@centos-7-24 tmp]# bash ping.sh
192.168.234.20 is shutdown
192.168.234.21 is shutdown
192.168.234.22 is running
192.168.234.23 is running
192.168.234.24 is running
192.168.234.25 is shutdown
192.168.234.26 is shutdown
192.168.234.27 is shutdown
192.168.234.28 is shutdown
192.168.234.29 is shutdown
192.168.234.30 is shutdown
END
2019/7/2 23:14:41