Shell条件语句与循环语句

128 阅读5分钟

条件语句

条件测试语句

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成。

测试过程,实现评估布尔声明,以便用在条件性环境下进行执行:

  • 若为真,则状态码变量 $? 返回0
  • 若为假,则状态码变量 $? 返回非0

格式:

 格式一: test 条件表达式
 
 格式二: [ 条件表达式 ]  //更常用

文件测试

格式:

 格式一: test 操作符 表达式
 
 格式二: [ 操作符 表达式 ]  

常用的文件测试操作符:

操作符作用
-d测试文件是否为目录文件(Directory)
-f测试文件是否为普通文件(File)
-e测试目录或文件是否存在(Exist)。建议使用-e,-a可能不准确。
-a测试目录或文件是否存在(Exist)
-r测试当前用户是否有权限读取(Read)
-w测试当前用户是否有权限写入(Write)
-x测试当前用户是否有权限执行(eXcute)
-L测试是否为符号链接(软链接文件)

例1:

[root@localhost ~]# test -d /etc   //测试是否为目录
[root@localhost ~]# echo $?    //状态码返回0,表示为真,是目录
0
[root@localhost ~]# test -f /etc/sysconfig/   //测试是否为普通文件
[root@localhost ~]# echo $?        //状态码返回1,表示为假,不是普通文件 1
1

image.png

例2:

[root@localhost ~]# [ -e /etc/shadow ]     //测试文件是否存在
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -a /etc/shadow ]     //测试文件是否存在
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ ! -a /etc/shadow ];echo $?
0
[root@localhost ~]# [ ! -e /etc/shadow ];echo $?
1

image.png

例3:

[root@localhost ~]# ll /etc/shadow
----------. 1 root root 1197 831 19:04 /etc/shadow
[root@localhost ~]# [ -r /etc/shadow ]    //测试root用户对文件是否拥有读取权限
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -w /etc/shadow ]   //测试root用户对文件是否拥有写入权限
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -x /etc/shadow ]   //测试root用户对文件是否拥有执行权限
[root@localhost ~]# echo $?
1

image.png

整数测试

整数值比较:

 [  整数变量1  操作符  整数变量2  ] 
 
 test 整数变量1  操作符  整数变量2

操作符:

操作符含义
-eq等于
-ne不等于
-gt大于
-lt小于
-le小于或等于
-ge大于或等于

例1:

[root@localhost ~]# [ 5 -lt 12 ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# a=3
[root@localhost ~]# b=7
[root@localhost ~]# [ $a -eq $b ] 
[root@localhost ~]# echo $?
1

image.png

例2:

[root@localhost ~]# ls | wc -l
13
[root@localhost ~]# test `ls |wc -l` -gt 10 && echo "文件数量大于10"
文件数量大于10

image.png

字符串测试

常用的测试操作符

  • =:字符串内容相同
  • !=:字符串内容不同,! 号表示相反的意思
  • -z:字符串内容为空
  • -n:字符是否存在

字符串比较常用的四种格式:

 [ "字符串1"  =  "字符串2"  ]   //测试字符串1和字符串2的内容是否相同
 [ "字符串1" !=  "字符串2”  ]   //测试字符串1和字符串2的内容是否不同
 [ -z "字符串" ]    //测试字符串是否为空,或者指定的变量是否为空值。(测试字符串的长度是否为零)
 [ -n "字符串" ]    //测试字符串是否存在,即是否不为空。(测试字符串的长度是否非零)

例1:

[root@localhost ~]# str1=a
[root@localhost ~]# str2=b
[root@localhost ~]# [ $str1 = $str2 ];echo $?    //测试变量1和变量2的值是否相同
1
[root@localhost ~]# [ $USER = root ];echo $?    //测试当前用户是否为root
0
[root@localhost ~]# [ $USER != root ];echo $?   //测试当前用户是否不为root
1
[root@localhost ~]# [ -z $HOME ];echo $?   //测试变量HOME是否为空值
1

image.png

例2:

[root@localhost ~]# empty=       //设置一个空值变量
[root@localhost ~]# echo $empty

[root@localhost ~]# [ -z $empty ] 
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -n $empty ] 
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -n "$empty" ]
[root@localhost ~]# echo $?
1

image.png

逻辑测试

逻辑测试用于连接多个测试条件,并返回整个表达式的值。 逻辑测试主要有"逻辑与","逻辑或","逻辑否"三种。

格式:

 格式一:[  表达式1  ]  逻辑运算符  [  表达式2  ] ...
 #例:[表达式1] && [表达式2]  等同于  [表达式1 -a 表达式2]  等同于  [[表达式1 && 表达式2]]
 #例:[表达式1] || [表达式2]  等同于  [表达式1 -o 表达式2]  等同于  [[表达式1 || 表达式2]]
 
 格式二:命令1  逻辑运算符  命令2  ... 

逻辑运算符:

  • -a或&& :逻辑与,“而且”的意思,全真才为真。
  • -o或|| :逻辑或,“或者”的意思,一真即为真。
  • ! :逻辑否。

二元运算符

例1:

[root@localhost ~]# [ 1 -lt 2 ] && [ 3 -eq 4 ]    //测试1是否小于2,同时3是否等于4
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ 1 -lt 2 ] || [ 3 -eq 4 ]     //测试1是否小于2,或者3是否等于4
[root@localhost ~]# echo $?
0

image.png

例2:

[root@localhost ~]# a=8
[root@localhost ~]# [ $a -ne 1 ]&&[ $a != 2 ]
[root@localhost ~]# echo $?
0
[root@localhost ~]#  [ $a -ne 1 -a  $a != 2 ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [[ $a -ne 1 &&  $a != 2 ]]
[root@localhost ~]# echo $?
0

image.png

三元运算符

 [ 表达式 ]  && a           //相当于 if语句单分支结构
 ​
 [ 表达式 ]  && a || b      //相当于 if语句双分支结构
 ​
 [ 表达式 ]  || b           //相当于 if [表达式];else

if语句

if单分支结构

格式:

 if  判断条件
 ​
 then  条件成立的分支代码
 ​
 fi                         //条件不成立直接结束

例: 判断已用磁盘空间是否大于80%,如果是就报警提示。

[root@localhost ~]# df |grep /dev/sda1
/dev/sda1                5232640  164016  5068624    4% /boot
[root@localhost ~]# df |grep /dev/sda1 |awk '{print $5}'
4%
[root@localhost ~]# df |grep /dev/sda1 |awk '{print $5}' |awk -F % '{print $1}'
4
[root@localhost ~]# vim test.sh

#!/bin/bash
a=$(df |grep /dev/sda1 |awk '{print $5}' |awk -F % '{print $1}')
if [ $a -gt 10 ]
 then
  echo "内存不足"
fi


[root@localhost ~]# chmod +x *
[root@localhost ~]# bash test.sh 
内存不足

if双分支结构

格式:

 if 判断条件
 then
     条件成立的分支代码
 else
     条件不成立的分支代码
 fi

例: 检测80端口是否在监听,如果是,则提示”网站服务已在运行“;如果否,则启动httpd服务。

[root@localhost ~]# vim 1.sh
#!/bin/bash
ss -ntap |grep :80 &>/dev/null
if [ $? -eq 0 ]
  then
    echo "http服务正在运行"
else
   echo "http服务未运行"
fi

[root@localhost ~]# bash 1.sh 
http服务未运行
[root@localhost ~]# systemctl start httpd.service 
[root@localhost ~]# bash 1.sh 
http服务正在运行

image.png

if多分支结构

格式:

 if 判断条件1
 then
     条件1为真的分支代码
 ​
 elif 判断条件2
 then
     条件2为真的分支代码
 ​
 elif 判断条件3
 then
     条件3为真的分支代码
 ​
 ...
 else
     以上条件都为假的分支代码
 ​
 fi

case语句

格式:

 case 变量引用 in
 模式1)
     命令分支1
     ;;
 模式2)
     命令分支2
     ;;
 ...
 *)
     默认命令分支
 esac

注意:

 case支持glob风格的通配符:
 * :任意长度任意字符
 ? :任意单个字符
 [0-9] :指定范围内的任意单个字符
 | :“或者”的意思,如: a|b

例:

[root@localhost ~]# vim km.sh
#!/bin/bash
read -p "请输入你的分数(0-100):" a
case $a in
100)
     echo "优秀"
     ;;
[89][0-9])
     echo "良好"
     ;;
[67][0-9])
     echo "及格"
     ;;
[0-9]|[1-5][0-9])
     echo "不及格"
     ;;
*)
     echo "输入有误,请重新输入,范围0-100"
esac

[root@localhost ~]# bash km.sh 
请输入你的分数(0-100):30
不及格
[root@localhost ~]# bash km.sh 
请输入你的分数(0-100):56
不及格
[root@localhost ~]# bash km.sh  
请输入你的分数(0-100):60
及格
[root@localhost ~]# bash km.sh 
请输入你的分数(0-100):95
良好
[root@localhost ~]# bash km.sh  
请输入你的分数(0-100):100
优秀
[root@localhost ~]# bash km.sh  
请输入你的分数(0-100):150
输入有误,请重新输入,范围0-100

循环语句

while循环语句

用法:

  • 读取不同的变量值,用来逐个执行同一组命令。
  • 使用场景:一般用于循环次数事先已知的场景。
  • 执行机制:遍历。

格式:

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

例1:打印0-10

[root@localhost ~]# a=0
[root@localhost ~]# while [ $a -le 10 ]
> do
> echo $a
> let a++
> done
0
1
2
3
4
5
6
7
8
9
10

image.png

例2:一直打印0

 [root@localhost ~]# a=0
 [root@localhost ~]# while [ $a -le 10 ]
 > do
 > echo $a
 > done
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0
 0
 ......

例3:批量添加用户

[root@localhost ~]# vim 1.sh

#!/bin/bash
i=1
while  [ $i -le 20 ]
do
useradd stu$i
echo "123456" |passwd --stdin stu$i &>/dev/null
if  [ $? -eq 0 ]
then
echo "stu${i}用户建立成功" 
else
echo "stu${i}用户建立失败"
fi
let i++
done

[root@localhost ~]# bash 1.sh
stu1用户建立成功
stu2用户建立成功
stu3用户建立成功
stu4用户建立成功
stu5用户建立成功
stu6用户建立成功
stu7用户建立成功
stu8用户建立成功
stu9用户建立成功
stu10用户建立成功
stu11用户建立成功
stu12用户建立成功
stu13用户建立成功
stu14用户建立成功
stu15用户建立成功
stu16用户建立成功
stu17用户建立成功
stu18用户建立成功
stu19用户建立成功
stu20用户建立成功

image.png

例4:猜商品价格

[root@localhost ~]# vim 2.sh

#!/bin/bash
m=`echo $[RANDOM%1000+1]`
t=0
while true
do
read -p "请输入商品价格(1-1000):" p
let t++
if   [ $m -eq $p ]
then
echo "恭喜你猜对了,商品价格是 $m"
echo "您一共猜了${t}次"
exit
elif [ $m -lt $p ]
then
echo "您猜的价格 高了"
else
echo "您猜的价格 低了"
fi
done

[root@localhost ~]# bash 2.sh
请输入商品价格(1-1000):500
您猜的价格 低了
请输入商品价格(1-1000):800
您猜的价格 高了
请输入商品价格(1-1000):700
您猜的价格 高了
请输入商品价格(1-1000):600
您猜的价格 低了
请输入商品价格(1-1000):650
您猜的价格 高了
请输入商品价格(1-1000):630
您猜的价格 高了
请输入商品价格(1-1000):610
您猜的价格 低了
请输入商品价格(1-1000):620
您猜的价格 高了
请输入商品价格(1-1000):615
您猜的价格 低了
请输入商品价格(1-1000):616
您猜的价格 低了
请输入商品价格(1-1000):617
您猜的价格 低了
请输入商品价格(1-1000):618
您猜的价格 低了
请输入商品价格(1-1000):619
恭喜你猜对了,商品价格是 619
您一共猜了13次

image.png

until循环语句

用法:

重复测试某个条件,只要条件不成立则反复执行。

格式:

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

例1:

[root@localhost ~]# until [ $a -gt 10 ]
> do
> echo $a
> let a++
> done
0
1
2
3
4
5
6
7
8
9
10

image.png

例2:

[root@localhost ~]# vim 3.sh

#!/bin/bash
sum=0
i=1
until [ $i -gt 10 ]
do
  sum=$[sum+i]
  let i++
done
echo "结果为 $sum"

[root@localhost ~]# chmod +x *
[root@localhost ~]# bash 3.sh
结果为 55

image.png