Linux 云计算集群架构师->第二十章 条件测试语句和 if 流程控制
第二十章 条件测试语句和 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 从键盘读入数据,赋给变量
# read r1 r2 #读取输入r1 r2变量的值
Hello Linux
# echo $r1 $r2
Hello Linux2.1.1 read 常用见用法及参数
read 选项
-p “提示信息”:等待 read 输入时,输出提示信息。
-t 秒数:read 命令会一直等待用户输入,使用此选项可以指定等待时间。
-n 字符数:read 命令只接受指定的字符数量,然后就会执行。
-s 隐藏输入内容,适用于机密信息的输入。
# read passwd #从标准输入读取一行并赋值给变量
passwrd读取多个值,从标准输入读取一行,直至遇到第一个空白符或换行符。把用户键入的第一个词
存到变量 first 中,把该行的剩余部分保存到变量 last 中
# read first last
aa bbread -s passwd 将你输入的东西隐藏起来,值赋给 passwd。这个用户隐藏密码信息
# read -s passwd #输入的东西隐藏起来,值赋给 passwd
# echo $passwd
123read -t 输入的时间限制
# read -t 2 username #超过两秒没有输入,直接退出,输入了,不敲回车,也不会保存变量值read -n 输入的长度限制(不常用)
# read -n 2 test #最多只接受 2 个字符
ab使用 -r 参数输入,允许让输入中的内容包括: 斜线识别为普通字符。
# read line
\echo
# echo $line
echo
# read -r line
\echo
# echo $line
\echoread -p 用于给出提示符,在前面的例子中我们使用了 echo –n “…“来给出提示符
# read -p "please input:" pass
please input:hello linux
# echo $pass
hello linux或
# echo -n "please input:"; read pass
please input:Hello Linux
# echo $pass
Hello Linuxecho -n 不输出行尾的换行符
read 综合实例
# vim read-test.sh
# cat read-test.sh !/bin/bash
read -p "请输入姓名:" NAME
read -p "请输入年龄:" AGE
read -p "请输入性别:" SEX
cat<<eof
*****************
你的基本信息如下:
姓名: $NAME
年龄:$AGE
性别:$SEX
****************
eof
# sh read-test.sh
请输入姓名:linux
请输入年龄:1970
请输入性别:man
*****************
你的基本信息如下:
姓名: linux
年龄:1970
性别:man
****************
20.2 流程控制语句 if
20.2.1 语法格式
if 条件
then
commands
fi
if 语句流程图:
根据我们的命令退出码来进行判断(echo $? =0),如果是 0,那么就会执行 then 后面的命令
# set paste #set paste 解决粘贴乱序问题
# vim if0.sh
# cat if0.sh !/bin/bash
if ls /tmp
then
echo "it's ok"
fi20.2.2 双分支 if 语句
语法格式:
if command ; then
commands
else
commands
fi
# vim if1.sh
# cat if1.sh !/bin/bash
read -p "检查目录是否存在,请输入目录:" dir
if ls $dir 2> /dev/null 1>&2
then
echo "目录存在"
else
echo "目录不存在"
fi
# sh if1.sh
检查目录是否存在,请输入目录:etc
目录不存在
# sh if1.sh
检查目录是否存在,请输入目录:/etc
目录存在20.2.3 多分支 if 语句
语法结构:
if 条件测试操作 1 ; then
commands
elif 条件测试操作 2 ; then
commands
elif 条件测试操作 3 ; then
commands
.......
else
commands
fi
判断用户在系统中是否存在,是否有家目录
# vim if2.sh
# 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
# sh if2.sh
input a user:yh
用户 yh 不存在
yh 家目录不存在
# 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” ]比较大小
# vim equ.sh
# 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 errfi
# sh equ.sh
err
ok
# vim test1.sh
# cat test1.sh
!/bin/bash
read -p "请输入第一个整数" a
read -p "请输入第二个整数" b
if [ $a -eq $b ]; then
echo "$a等于$b,两个数字相等"
else
echo "$a不等于$b,两个数字不相等"
fi
# sh test1.sh
请输入第一个整数10
请输入第二个整数10
10等于10,两个数字相等20.3.2 字符串比较
参数说明示例==等于则为真[ “$a” == “$b” ]!=不相等则为真[ “$a” != “$b” ]-z 字符串字符串的长度为零则为真[ -z “$a” ]-n 字符串字符串的长度不为空则为真[ -n “$a” ]str1 > str2str1 大于 str2 为真[ str1 \> str2 ]str1 < str2str1 小于 str2 为真[ str1 \< str2 ]根据用户名判断是否是超级管理员
# vim test2.sh
# cat test2.sh !/bin/bash
read -p "请输入你的名子" name
if [ $name == "root" ]; then
echo "你是管理员"
else
echo "不是管理员"
fi
# sh test2.sh
请输入你的名子dior
不是管理员
# sh test2.sh
请输入你的名子root
你是管理员在做字符串大小比较的时候,注意字符串的顺序
大于号和小于号必须转义,要不然 SHELL 会把它当成重定向符号
大于和小于它们的顺序和 sort 排序是不一样的
在 test 比较测试中,它使用的是 ASCII 顺序,大写字母是小于小写字母的;sort 刚好相反扩展: ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准 ISO/IEC 646。
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 ]# [ -e /etc/passwd ] && echo "是文件" || echo "不是文件" 是文件是文件
<p># [ -e /etc/pass ] && echo "是文件" || echo "不是文件" 不是文件不是文件 不是文件</p>
<p># touch testa</p>
<p># [ -s testa ]; echo $?</p>
1
<p># echo a1b2c3 > testa</p>
<p># test -s testa;echo $?</p>
0清空日志目录脚本
# vim log.sh
# 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# 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 权限掩码
# vim /etc/profile
# 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
# bash umask.sh
i am root :umask 022符号定义符号定义()单小括号(())双小括号[]单中括号[[]]双中括号{}大括号*[[… ]] 运算符是[… ]运算符的扩充;[[… ]]能够支持 ,< 、>等符号且不需要转义符**
# if [[ $USER == r ]]; then echo true; else echo false;fi
true #注: [[ $USER == r ]]对比时, r* 表示以 r 开头的任意长度字符串,这样就包括 root
# if [ $USER == r ] ; then echo true ; else echo false ; fi
#注: [ $USER == r* ]对比时, r* 就表示 r*# if [[$USER == oot]]; then echo true; else echo false; fi
[[ 。。。 ]]和[ 。。。],() 和(())的区别汇总
()单小括号:
多条命令执行:
括号中的命令将会新开一个子 shell 顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
单小括号,(cmd1;cmd2;cmd3) 新开一个子 shell 顺序执行命令 cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。
# ( a1=1,b1=2,c1=3 )
# echo $a1 $b1 $c1
1 2 3多条命令执行:
{} 花括号,大括号,{ cmd1;cmd2;cmd3;} 在当前 shell 顺序执行命令 cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。
# { a1=1;b1=2;c1=3; }
# echo $a1 $b1 $c1
1 2 31、所有的字符与逻辑运算符直接用“空格”分开,不能连到一起。
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 中的任意单一字符匹配 0-9 中的任意单一字符 如:{string1,string2,...}匹配 sring1 或 string2 (或更多)其中一个字符串# ls /etc/*.conf
# ls /etc/???.conf
# touch /opt/a{1,2,3}.txt
# ls /opt/a.txt
/opt/a1.txt/opt/a3.txt
# ls /opt/a[!12].txt
/opt/a3.txt
# ls /opt/a.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
# touch {abc{1..3},def4}.txt
# ls .txt
abc1.txtabc2.txtabc3.txtdef4.txt
20.5 实战-3 个 shell 脚本实战
20.5.1 实战 1:编写脚本检查服务器运行状态
# vim status.sh
# 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 服务没有运行,已经尝试启动该服务"
fielse
echo "执行脚本的格式"
echo "sh $0 服务名"
fi
# sh status.sh rsyslog
rsyslog 服务正常运行
# bash status.sh httpd
httpd 服务没有运行,已经尝试启动该服务20.5.2 实战 2:
根据学生的成绩判断学生的优劣
# vim check.sh
# 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
# bash check.sh
请输入你的成绩 65
还不错
# bash check.sh
请输入你的成绩 75
非常好
# bash check.sh
请输入你的成绩 85
非常好
# bash check.sh
请输入你的成绩 95
你很优秀20.5.3 实战 3:
每周一晚上 3:00 ,备份数据库服务器上 webdb 库的所有数据到系统的/mysqlbak 目录里,使用系统日期做备份文件名。
# vim mysqlbak.sh
# 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 目录来做实验
# vim etcback.sh
# 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 !!!"
# chmod +x etcback.sh
# ./etcback.sh
# crontab -e
# 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 脚本实战
文档来源:51CTO技术博客https://blog.51cto.com/u_2999064/3180873
页:
[1]