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

Linux 云计算集群架构师->第二十章 条件测试语句和 if 流程控制

来源:互联网 收集:自由互联 发布时间:2022-07-05
第二十章 条件测试语句和 if 流程控制语句的使用 (上课时间2021-07-13,笔记整理时间2021-07-24) 本节所讲内容: 20.1 read 命令键盘读取变量的值 20.2 流程控制语句 if 20.3 test 测试命令 20.4 流

第二十章 条件测试语句和 if 流程控制语句的使用

(上课时间2021-07-13,笔记整理时间2021-07-24)

本节所讲内容:

20.1 read 命令键盘读取变量的值

20.2 流程控制语句 if

20.3 test 测试命令

20.4 流程控制过程中复杂条件和通配符

20.5 实战-2 个 shell 脚本实战

20.1 read 命令键盘读取变量的值

从键盘读取变量的值,通常用在 shell 脚本中与用户进行交互的场合。该命令可以一次读取多个变量的值,变量和输入的值都需要使用空格隔开。在 read 命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量 REPLY

read 从键盘读入数据,赋给变量

[root@CentOS83 ~]# read r1 r2 #读取输入r1 r2变量的值 Hello Linux [root@CentOS83 ~]# echo $r1 $r2 Hello Linux

2.1.1 read 常用见用法及参数

read 选项

-p “提示信息”:等待 read 输入时,输出提示信息。

-t 秒数:read 命令会一直等待用户输入,使用此选项可以指定等待时间。

-n 字符数:read 命令只接受指定的字符数量,然后就会执行。

-s 隐藏输入内容,适用于机密信息的输入。

[root@CentOS83 ~]# read passwd #从标准输入读取一行并赋值给变量 passwrd

读取多个值,从标准输入读取一行,直至遇到第一个空白符或换行符。把用户键入的第一个词存到变量 first 中,把该行的剩余部分保存到变量 last 中

[root@CentOS83 ~]# read first last aa bb

read -s passwd 将你输入的东西隐藏起来,值赋给 passwd。这个用户隐藏密码信息

[root@CentOS83 ~]# read -s passwd #输入的东西隐藏起来,值赋给 passwd [root@CentOS83 ~]# echo $passwd 123

read -t 输入的时间限制

[root@CentOS83 ~]# read -t 2 username #超过两秒没有输入,直接退出,输入了,不敲回车,也不会保存变量值

read -n 输入的长度限制(不常用)

[root@CentOS83 ~]# read -n 2 test #最多只接受 2 个字符 ab

使用 -r 参数输入,允许让输入中的内容包括: 斜线识别为普通字符。

[root@CentOS83 ~]# read line \echo [root@CentOS83 ~]# echo $line echo [root@CentOS83 ~]# read -r line \echo [root@CentOS83 ~]# echo $line \echo

read -p 用于给出提示符,在前面的例子中我们使用了 echo –n “…“来给出提示符

[root@CentOS83 ~]# read -p "please input:" pass please input:hello linux [root@CentOS83 ~]# echo $pass hello linux #或 [root@CentOS83 ~]# echo -n "please input:"; read pass please input:Hello Linux [root@CentOS83 ~]# echo $pass Hello Linux

echo -n 不输出行尾的换行符

read 综合实例

[root@CentOS83 ~]# vim read-test.sh [root@CentOS83 ~]# cat read-test.sh #!/bin/bash read -p "请输入姓名:" NAME read -p "请输入年龄:" AGE read -p "请输入性别:" SEX cat<<eof ********************* 你的基本信息如下: 姓名: $NAME 年龄:$AGE 性别:$SEX ******************** eof [root@CentOS83 ~]# sh read-test.sh 请输入姓名:linux 请输入年龄:1970 请输入性别:man ********************* 你的基本信息如下: 姓名: linux 年龄:1970 性别:man ********************

20.2 流程控制语句 if

20.2.1 语法格式

​ if 条件

​ then

​ commands

​ fi

​ if 语句流程图:

image-20210724220624011

根据我们的命令退出码来进行判断(echo $? =0),如果是 0,那么就会执行 then 后面的命令

[root@CentOS83 ~]# set paste #set paste 解决粘贴乱序问题 [root@CentOS83 ~]# vim if0.sh [root@CentOS83 ~]# cat if0.sh #!/bin/bash if ls /tmp then echo "it's ok" fi

20.2.2 双分支 if 语句

语法格式:

if command ; then

​ commands

else

​ commands

fi

image-20210725075027679

[root@CentOS83 ~]# vim if1.sh [root@CentOS83 ~]# cat if1.sh #!/bin/bash read -p "检查目录是否存在,请输入目录:" dir if ls $dir 2> /dev/null 1>&2 then echo "目录存在" else echo "目录不存在" fi [root@CentOS83 ~]# sh if1.sh 检查目录是否存在,请输入目录:etc 目录不存在 [root@CentOS83 ~]# sh if1.sh 检查目录是否存在,请输入目录:/etc 目录存在

20.2.3 多分支 if 语句

语法结构:

if 条件测试操作 1 ; then

commands

elif 条件测试操作 2 ; then

commands

elif 条件测试操作 3 ; then

commands

.......

else

commands

fi

image-20210725080836235

判断用户在系统中是否存在,是否有家目录

[root@CentOS83 ~]# vim if2.sh [root@CentOS83 ~]# cat if2.sh #!/bin/bash read -p "input a user:" user if grep $user /etc/passwd; then echo "用户 $user 已经存在" elif ls -d /home/$user > /dev/null 2>&1; then echo "$user 不存在,但家目录存在" else echo "用户 $user 不存在" echo "$user 家目录不存在" fi [root@CentOS83 ~]# sh if2.sh input a user:yh 用户 yh 不存在 yh 家目录不存在 [root@CentOS83 ~]# sh if2.sh input a user:dior dior:x:1000:1000::/home/dior:/bin/bash 用户 dior 已经存在

20.3 test 测试命令

Shell 中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试

格式:test 测试条件

如果结果是对的,也叫结果为真,用$?=0 表示,反之为假,用非 0 表示

equal 等于;not equal to 不等于;greater than 大于; less than 小于;

20.3.1 数值比较

参数 说明 示例 -eq 等于则为真 [ “$a” -eq “$b” ] -ne 不等于则为真 [ “$a” -ne “$b” ] -gt 大于则为真 [ “$a” -gt “$b” ] -ge 大于等于则为真 [ “$a” -ge “$b” ] -lt 小于则为真 [ “$a” -lt “$b” ] -le 小于等于则为真 [ “$a” -le “$b” ]

比较大小

[root@CentOS83 ~]# vim equ.sh [root@CentOS83 ~]# cat equ.sh #!/bin/bash if test 20 -eq 10; then echo ok else echo err fi if [ 20 -eq 20 ];then #注意括号中的空格 echo ok else echo err fi [root@CentOS83 ~]# sh equ.sh err ok [root@CentOS83 ~]# vim test1.sh [root@CentOS83 ~]# cat test1.sh #!/bin/bash read -p "请输入第一个整数" a read -p "请输入第二个整数" b if [ $a -eq $b ]; then echo "$a等于$b,两个数字相等" else echo "$a不等于$b,两个数字不相等" fi [root@CentOS83 ~]# sh test1.sh 请输入第一个整数10 请输入第二个整数10 10等于10,两个数字相等

20.3.2 字符串比较

参数 说明 示例 == 等于则为真 [ “$a” == “$b” ] != 不相等则为真 [ “$a” != “$b” ] -z 字符串 字符串的长度为零则为真 [ -z “$a” ] -n 字符串 字符串的长度不为空则为真 [ -n “$a” ] str1 > str2 str1 大于 str2 为真 [ str1 \> str2 ] str1 < str2 str1 小于 str2 为真 [ str1 \< str2 ]

根据用户名判断是否是超级管理员

[root@CentOS83 ~]# vim test2.sh [root@CentOS83 ~]# cat test2.sh #!/bin/bash read -p "请输入你的名子" name if [ $name == "root" ]; then echo "你是管理员" else echo "不是管理员" fi [root@CentOS83 ~]# sh test2.sh 请输入你的名子dior 不是管理员 [root@CentOS83 ~]# sh test2.sh 请输入你的名子root 你是管理员

在做字符串大小比较的时候,注意字符串的顺序

大于号和小于号必须转义,要不然 SHELL 会把它当成重定向符号

大于和小于它们的顺序和 sort 排序是不一样的

在 test 比较测试中,它使用的是 ASCII 顺序,大写字母是小于小写字母的;sort 刚好相反扩展: ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准 ISO/IEC 646。

image-20210725111824938

20.3.3 文件比较

参数 说明 示例 -e 文件名. 如果文件或目录存在则为真 [ -e file ] -r 文件名. 如果文件存在且可读则为真 [ -r file ] -w 文件名. 如果文件存在且可写则为真 [ -w file ] -x 文件名. 如果文件存在且可执行则为真 [ -x file ] -s 文件名. 如果文件存在且至少有一个字符则为真 [ -s file ] -d 文件名. 如果文件存在且为目录则为真 [ -d file ] -f 文件名. 如果文件存在且为普通文件则为真 [ -f file ] -c 文件名. 如果文件存在且为字符型文件则为真 [ -c file ] -b 文件名.. 如果文件存在且为块特殊文件则为真 [ -b file ] file1 -nt fle2 检查 file1 是否比 file2 新 [ file1 -nt file2 ] file1 -ot file2 检查 file1 是否比 file2 旧 [ file1 -ot file2 ] [root@CentOS83 ~]# [ -e /etc/passwd ] && echo "是文件" || echo "不是文件" 是文件是文件 [root@CentOS83 ~]# [ -e /etc/pass ] && echo "是文件" || echo "不是文件" 不是文件不是文件 不是文件 [root@CentOS83 ~]# touch testa [root@CentOS83 ~]# [ -s testa ]; echo $? 1 [root@CentOS83 ~]# echo a1b2c3 > testa [root@CentOS83 ~]# test -s testa;echo $? 0

清空日志目录脚本

[root@CentOS83 ~]# vim log.sh [root@CentOS83 ~]# cat log.sh #!/bin/bash # 这是清空日志脚本 # 判断当前用户是否为 root if [ $USER != "root" ];then echo "脚本需要 root 用户执行" exit 10 #直接退出,并返回 10 fi # 判断文件是否存在,!取反 if [ ! -f /var/log/messages ];then echo "文件不存在" exit 12 fi # 保留最近 100 行的日志内容。 tail -100 /var/log/messages > /var/log/mesg.tmp # 日志清空 > /var/log/messages mv /var/log/mesg.tmp /var/log/messages echo "log clean up" exit #退出 bash,并返回一个值 注:退出码 exit ,取值范围是 0-255,超过后值循环 0-255 [root@CentOS83 ~]# sh log.sh log clean up

20.4 流程控制过程中复杂条件和通配符

20.4.1 判断第一种:两个条件都为真或有一个为真就执行

if [ 条件判断一 ] && [ 条件判断二 ]; then

命令一

elif [ 条件判断三 ] || [ 条件判断四 ]; then

命令二

else

执行其它

fi

#!/bin/bash if [ -d /etc ] && [ -d /root ];then #判断/etc目录 &&和 /root目录 echo "etc 和 root 目录都存在" fi if [ -d /etc ] || [ -d /root ];then #判断/etc目录 ||或 /root目录 echo "etc 或 root 目录至少有一个存在" fi

判断第二种

if [条件判断一 -a 条件判断二 -a 条件判断三]; then

elif [条件判断三 -o 条件判断四 ]; then

else

执行其它

fi

#!/bin/bash if [ -d /etc -a -d /root ];then echo "etc 和 root 目录都存在" fi if [ -d /etc -o -d /root ];then echo "etc 或 root 目录至少有一个存在" fi

判断第三种

if [[ 条件判断一 && 条件判断二 ]]; then

elif [[ 条件判断三 || 条件判断四 ]]; then

else

执行其它

fi

#!/bin/bash if [[ -d /etc && -d /root ]];then echo "etc 和 root 目录都存在" fi if [[ -d /etc || -d /root ]];then echo "etc 或 root 目录至少有一个存在" fi

设置 umask 权限掩码

[root@CentOS83 ~]# vim /etc/profile

image-20210725100028885

[root@CentOS83 ~]# vim umask.sh #!/bin/bash #-gn 表示用名称显示 group。-un 表示用名称方式显示用户名,判断组和用户是否相同。 if [ $UID -gt 199 ] && [ "`id -gn`" = "`id -un`" ]; then echo "umask 002" else echo "i am root :umask 022" fi [root@CentOS83 ~]# bash umask.sh i am root :umask 022 符号 定义 符号 定义 () 单小括号 (()) 双小括号 [] 单中括号 [[]] 双中括号 {} 大括号

*[[… ]] 运算符是[… ]运算符的扩充;[[… ]]能够支持 ,< 、>等符号且不需要转义符**

[root@CentOS83 ~]# if [[ $USER == r* ]]; then echo true; else echo false;fi true #注: [[ $USER == r* ]]对比时, r* 表示以 r 开头的任意长度字符串,这样就包括 root [root@CentOS83 ~]# if [ $USER == r* ] ; then echo true ; else echo false ; fi #注: [ $USER == r* ]对比时, r* 就表示 r* [root@CentOS83 ~]# if [[$USER == [a-z]oot]]; then echo true; else echo false; fi #[[ 。。。 ]]和[ 。。。],() 和(())的区别汇总

()单小括号:

多条命令执行:

括号中的命令将会新开一个子 shell 顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。

单小括号,(cmd1;cmd2;cmd3) 新开一个子 shell 顺序执行命令 cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。

[root@CentOS83 ~]# ( a1=1,b1=2,c1=3 ) [root@CentOS83 ~]# echo $a1 $b1 $c1 1 2 3

多条命令执行:

{} 花括号,大括号,{ cmd1;cmd2;cmd3;} 在当前 shell 顺序执行命令 cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。

[root@CentOS83 ~]# { a1=1;b1=2;c1=3; } [root@CentOS83 ~]# echo $a1 $b1 $c1 1 2 3

1、所有的字符与逻辑运算符直接用“空格”分开,不能连到一起。

2、在[… ]表达式中,常见的> 、<需要加转义符\,大小比较

3、进行逻辑运算符&& 、||比较时;如果用的[ ]符号,则用在外面,如[… ] && [… ] || [ …]如果在[…]里面进行逻辑与或的比较,则用-a、-o 进行表示,如[ x = y –a x < z –o x > m ]

4、[[… ]] 运算符只是[… ]运算符的扩充;能够支持< 、>符号运算不需要转义符;它还是以字符串比较大小。里面支持逻辑运算符 || 、 && , 不再使用-a 、-o

5、[[…]] 用 && 而不是 -a 表示逻辑“与”;用 || 而不是 -o 表示逻辑“或”

6、[[… ]]可以进行算术扩展,而[ ... ]不可以

7、[[...]]能用正则,而[...]不行

8、双括号(( ))用于数学表达式

9、双方括号号[[ ]]用于高级字符串处理,比如“模糊匹配”

10、[[]]对于字符串的比较支持并不好,尤其在使用[[]]和<>符号进行比较的时候会出现返回值错误的情况。

20.4.2 shell 中的通配符

shell 常见通配符:

字符 含义 * 匹配 0 或多个字符 ? 匹配任意一个字符 [abcd] 匹配 abcd 中的任意单一字符 [!abcd] 匹配 除 abcd 中的任意单一字符 [0-9] 匹配 0-9 中的任意单一字符 如:[a-z] {string1,string2,...} 匹配 sring1 或 string2 (或更多)其中一个字符串 [root@CentOS83 ~]# ls /etc/*.conf [root@CentOS83 ~]# ls /etc/???.conf [root@CentOS83 ~]# touch /opt/a{1,2,3}.txt [root@CentOS83 ~]# ls /opt/a[13].txt /opt/a1.txt /opt/a3.txt [root@CentOS83 ~]# ls /opt/a[!12].txt /opt/a3.txt [root@CentOS83 ~]# ls /opt/a[1-3].txt /opt/a1.txt /opt/a2.txt /opt/a3.txt

大括号拓展。(通配)将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。第一种:对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为 a.txt b.txt。第二种:对大括号中以点点(..)分割的顺序文件列表起拓展作用,如:touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt

[root@CentOS83 ~]# touch {abc{1..3},def4}.txt [root@CentOS83 ~]# ls *.txt abc1.txt abc2.txt abc3.txt def4.txt

20.5 实战-3 个 shell 脚本实战

20.5.1 实战 1:编写脚本检查服务器运行状态

[root@CentOS83 ~]# vim status.sh [root@CentOS83 ~]# cat status.sh #!/bin/bash if [ $# -ge 1 ]; then systemctl status $1 > /dev/null if [ $? -eq 0 ];then echo "$1 服务正常运行" else systemctl start $1 echo "$1 服务没有运行,已经尝试启动该服务" fi else echo "执行脚本的格式" echo "sh $0 服务名" fi [root@CentOS83 ~]# sh status.sh rsyslog rsyslog 服务正常运行 [root@CentOS83 ~]# bash status.sh httpd httpd 服务没有运行,已经尝试启动该服务

20.5.2 实战 2:

根据学生的成绩判断学生的优劣

[root@CentOS83 ~]# vim check.sh [root@CentOS83 ~]# cat check.sh #!/bin/bash read -p "请输入你的成绩 " cj if [ $cj -ge 0 ] && [ $cj -le 59 ] ; then echo "不及格,请补考" elif [ $cj -ge 60 ] && [ $cj -le 70 ] ; then echo "还不错" elif [ $cj -ge 71 ] && [ $cj -le 85 ] ; then echo "非常好" elif [ $cj -ge 86 ] && [ $cj -le 100 ] ; then echo "你很优秀" else echo "成绩的有效范围是0-100之间" fi [root@CentOS83 ~]# bash check.sh 请输入你的成绩 65 还不错 [root@CentOS83 ~]# bash check.sh 请输入你的成绩 75 非常好 [root@CentOS83 ~]# bash check.sh 请输入你的成绩 85 非常好 [root@CentOS83 ~]# bash check.sh 请输入你的成绩 95 你很优秀

20.5.3 实战 3:

每周一晚上 3:00 ,备份数据库服务器上 webdb 库的所有数据到系统的/mysqlbak 目录里,使用系统日期做备份文件名。

[root@CentOS83 ~]# vim mysqlbak.sh [root@CentOS83 ~]# cat mysqlbak.sh #!/bin/bash backnamefile=`date +%Y-%m-%d` bakdir=/mysqlbak user=root password=root dbname=webdb [ -d $bakdir ] || mkdir $bakdir mysqldump -u$user -p$password --flush-logs $dbname > $bakdir/${baknamefile}-webdb.sql

这里以/etc 目录来做实验

[root@CentOS83 ~]# vim etcback.sh [root@CentOS83 ~]# cat etcback.sh #!/bin/bash baknamefile=`date +%Y-%m-%d` bakdir=/etcbak srcdir=/etc [ -d $bakdir ] || mkdir $bakdir tar czvf ${bakdir}/${baknamefile}-etc.tar.gz ${srcdir} echo "====================================================" ls -lh ${bakdir}/${baknamefile}-etc.tar.gz echo "back etc is ok !!!" [root@CentOS83 ~]# chmod +x etcback.sh [root@CentOS83 ~]# ./etcback.sh [root@CentOS83 ~]# crontab -e [root@CentOS83 ~]# crontab -l 0 3 * * * /root/etcbak.sh > /dev/null 2>&1

总结:

20.1 read 命令键盘读取变量的值

20.2 流程控制语句 if

20.3 test 测试命令

20.4 流程控制过程中复杂条件和通配符

20.5 实战-3 个 shell 脚本实战

网友评论