Shell条件判断与流控匹配

目录

目录

一、shell条件测试

1. 格式

2. 不同括号的区别

3. 文件测试

4. 整数值比较

5. 字符串比较

6. 逻辑测试(短路运算)

7. ()和{}

二、流程控制if

1. 单分支结构

2. 双分支结构

3. 多分枝结构

4. 嵌套结构

5. 应用示例

三、模式匹配case

1. case语法结构

2. 模式匹配示例


一、shell条件测试

shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0时表示成功,否则表示失败或者异常。

1. 格式

test测试文件的表达式是否成立

格式1:test  [选项]  [对象]

格式2:[ 条件表达式 ]   [ 操作符 文件或目录 ]

需要有空格,否则会失败;测试是否成功使用 $?,返回值为0,代表成功,否则失败。

格式3:[[  条件表达式  ]]

操作符:

-d 测试是否为目录(Directory)
-e 测试目录或文件是否存在(Exist)
-a 测试目录或文件是否存在(Exist)
-f 测试是否为文件(File)
-r 测试当前用户是否有权限读取(Read)
-w 测试当前用户是否有权限写入(Write)
-x 测试当前用户是否有权限执行(eXcute)
-L 测试是否为软连接文件

属性测试补充:

  • -s FILE:是否存在且非空
  • -t fd:fd文件描述符是否在某终端已经打开
  • -N FILE:文件自从上一次被读取之后是否被修改过
  • -O FILE:当前有效用户是否为文件属主
  • -G FILE:当前有效用户是否为文件属组 

2. 不同括号的区别

① 单括号 (...) 常用的用法有两种,一种是用于shell中的数组,一种是获取命令执行后的结果

② (( ))只能进行整数比较,不能用于字符串比较,括号中的变量可以省略$符号前缀,当然也可以带着;运算符前后可以有空格,也可以没有;多个运算符用逗号分隔

③ [ ]和[[ ]]的区别:

  • 本质上,[ ]和test是等价的,都是命令,而[[ ]]是关键字,所以重定向等字符在[ ]中会被认为成重定向,而在[[ ]]中是比较符号的意思
  • &&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不使用双括号, 则为if [ $a != 1] && [ $a != 2 ]或者if [ $a != 1 -a $a != 2 ]
  • [[]]支持字符串的模式匹配,[]不支持。使用=或==进行字符串比较,等号右边的可以作为一个模式,比如[[ "hello" == hell? ]]为真。模式匹配不能加引号,否则会作为固定字符串,如[[ "hello" == "hell?" ]]为假

3. 文件测试

根据给定的路径名称,判断对应的是文件还是目录,或者判断文件是否可读、可写、可执行等。

[root@localhost ~]# test -d /root ; echo $?
0
[root@localhost ~]# test -f /root ; echo $?
1
[root@localhost ~]# [ -d /root ];echo $?
0
[root@localhost ~]# [ -f /root ];echo $?
1
[root@localhost ~]# test -e /root && echo "yes"
yes
&&表示且的意思,前面的表达式成立才会输出yes

a和e的区别:

[root@localhost ~]# [ ! -e /root ];echo $?
1
[root@localhost ~]# [ ! -a /root ];echo $?
0

-a取反存在bug,建议使用-e。

4. 整数值比较

根据给定的两个整数值,判断第一个数与第二个数的关系,如是否大于、等于、小于第二个数。格式:[ 整数1 -操作符 整数2 ] 公式

操作符及C语言风格:

在[]以及 test 中使用的比较符号 在(())和 []]中使用的比较符号 说明
-eq ==或= 相等,全拼为equal
-ne != 不相等,全拼为 not equal
-gt > 大于,全拼为 greater than
-ge >= 大于等于,全拼为 greater equal
-lt < 小于,全拼为less than
-le <= 小于等于,全拼为 less equal

示例:

[root@localhost ~]# a=1;b=2
[root@localhost ~]# [ $a -eq $b ];echo $?
1
[root@localhost ~]# ((1<2));echo $?
0
[root@localhost ~]# (( a<$b));echo $?
0

注意:

  • 双括号 (( ))是用于整数运算和逻辑运算的,不能用于其他类型数据的运算;双括号中引用变量可以加$也可以不加;运算符前后可以有空格,也可以没有;多个运算符用逗号分隔
  • 在[ ] [[ ]]中,数字对比不支持>,<,=等;在(( )) 中,数字对比是支持>,<,=的,但不支持-eq,-ne,-gt等
  • 在[ ] [[ ]]中,=与==表示判断,是等价的;在(( )) 中,=表示赋值,==表示判断

5. 字符串比较

通常用来检查用户输入、系统环境等是否满足条件,在提供交互式操作的shell脚本中,也可以用来判断用户输入的位置参数是否符合要求。

常用的测试操作符:

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

格式:

  • [ 字符串1 = 字符串2 ] 是否相同
  • [ 字符串1 != 字符串2 ] 是否不相同
  • [ -z 字符串 ] 是否为空
  • [ -n 字符串 ] 字符是否存在

示例:

[root@localhost ~]# test1=a;test2=b
[root@localhost ~]# [ $test1 = $test2 ];echo $?
1
[root@localhost ~]# [ $USER = root ] && echo true || echo flase
true
[root@localhost ~]# [ $USER != root ] && echo true || echo flase
flase

注意:

  • 使用[ ]对比字符串时,末尾一定要加上x(或者a、b等)一个字符,因为[ $ax == "ab"x ]如果没有了x ,并且$a是"",这个语句会翻译成if [ == "ab" ],左边相当于没有东西了,会报语法错误。或者使用[[ ]],就不需要x了
  • 使用<或者>时,如果是用[ ],需要用转义\,如\>
  • 使用-z -n时,如果是用 [ ],则字符串一定要加双引号(单引号都不行),如:[ -n "$a" ];如果是用[[ ]],则加不加双引号都可以(但一定不能加单引号)

6. 逻辑测试(短路运算)

格式:

格式1:[ 表达式1 ] 操作符 [ 表达式2 ] ...     

格式2:命令1 操作符 命令2 ...

且&&:cmd1 && cmd2,全真才真,一假即假

或||:cmd1 || cmd2,全假才假,一真即真

常见条件

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

括号组合使用:

  • [[ ]]只能使用&& ||,不能使用-a或-o。&&和||写在括号里或外都可以
  • (( ))与[[ ]]相同,只不过可以省略变量前的$,且只能用于整数比较
  • [ ]既可以使用&& ||,也可以使用-a或-o。但&&和||必须在括号外,-a或-o必须在括号内 
括号内连接 括号外连接
[ ] -a  -o &&  ||
[[ ]] &&  || &&  ||

示例:判断b>a且b

a=1;b=2;c=3
if (( b > a && b < c ))                 #正确
if (( b > a )) && (( b < c ))           #正确
if [[ $b -gt $a ]] && [[ $b -lt $c ]]   #正确
if [[ $b -gt $a && $b -lt $c ]]         #正确
if [ $b -gt $a ] && [ $b -lt $c ]       #正确
if [ $b -gt $a -a $b -lt $c ]           #正确

示例2:判断判断a

[ $a -lt $b ] && echo t || echo f

注意在[[ ]]用法中:

  • 当使用==和!=操作符时,操作符右边字符用通配符
  • 当使用=~操作符时,操作符右边的字符用正则表达式  

7. ()和{}

(CMD1;CMD2;...)和 { CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行

区别:

[root@localhost ~]# ( cd /opt;ls );pwd           #()会开启子shell
rh
/root 
[root@localhost ~]# { cd /opt;ls; };pwd          # { } 不会开启子shell
rh
/opt

二、流程控制if

1. 单分支结构

语法:

if 判断条件;then   
条件为真的分支代码
fi

示例:由用户输入用户名,如果用户不存在,则创建该用户

#!/bin/bash
read -p "输入用户名: " name
id $name &> /dev/null
if [ $? -ne 0 ];then
	useradd $name
fi

2. 双分支结构

语法:

if 判断条件; then
 条件为真的分支代码
else
 条件为假的分支代码
fi

示例:由用户输入用户名,如果用户不存在,则创建该用户,并设置密码为123456;否则,提示用户已经存在

#!/bin/bash
read -p "输入用户名: " name
if  id $name &> /dev/null;then
	echo "$name已存在"
else
	useradd $name
	echo "123456" | passwd --stdin $name &> /dev/null
	echo "$name用户已创建,密码是123456"
fi

3. 多分枝结构

语法:

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

示例:根据成绩范围查询优良情况

#!/bin/bash
read -p "请输入你的考试分数:" grade
if   [ $grade -ge 85 ] && [ $grade -le 100 ];then
        echo "你的成绩为$grade,成绩优秀"
elif [ $grade -ge 70 ] && [ $grade -le 84 ];then
        echo "你的成绩为$grade,成绩良好"
elif [ $grade -ge 60 ] && [ $grade -le 69 ];then
        echo "你的成绩为$grade,成绩合格"
elif [ $grade -ge 0 ] && [ $grade -le 59 ];then
        echo "你的成绩为$grade,成绩不合格"
else
        echo "你的输入有误,请重新输入"
bash $0
fi

4. 嵌套结构

语法:

if [ condition1 ]; then
    嵌套的 if 语句
    if [ condition2 ]; then
    嵌套的命令1
    else
    嵌套的命令2
    fi
else
    命令3
fi

示例:由用户输入用户名,如果用户存在提示存在;如果用户不存在,由用户输入密码,密码长度需要大于7位,否则提示密码不合格

#!/bin/bash
read -p "输入用户名: " name
id $name &> /dev/null
if [ $? -eq 0 ];then
echo "$name已存在"
else
        useradd $name
        echo "$name用户名创建成功"
        read -p "请输入用户密码: "  pass
                if [ ${#pass}  -ge  7  ];then
                echo "$pass" | passwd --stdin $name
                echo "$name 用户密码是 $pass"
                else
                echo "密码不合格" 
                fi
fi

5. 应用示例

示例1:石头剪刀布

#!/bin/bash 
read -p "请输入 1(石头) 2(剪刀) 3(布):" h
m=`echo $[RANDOM%3+1]`
 
if [ $h -eq $m ]
then
echo "平局!"
elif [ $h -eq 1 -a $m -eq 2 -o $h -eq 2 -a $m -eq 3 -o $h -eq 3 -a $m -eq 1 ];then
echo "您赢了!"
else
echo "您输了!"
fi

示例2:鸡兔同笼

#!/bin/bash
read -p "脚的数量:" jiao
read -p "头的数量:" tou
a=2
JIAO=$[tou*a]
if [ $jiao -ge 0 ];then
        tujiao=$[jiao-JIAO]
        tnum=$[tujiao/a]
        jnum=$[tou-tnum]
echo "鸡的数量:$jnum"
echo "兔的数量:$tnum"
fi

示例3:服务器磁盘空间不足邮件告警

[root@localhost ~]# vim mail.sh
#!/bin/bash
use=80
disk=`df|grep "sd"|tr -s " "|cut -d " " -f5|cut -d "%" -f1` 
[ $disk -ge $use ] && echo "磁盘使用率过高"|mail -s test *********@qq.com
[root@localhost ~]# vim /etc/mail.rc
set from=*********@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=********@qq.com
set smtp-auth-password=qqwsd*********
[root@localhost ~]# dd if=/dev/zero of=/boot/bigfile
[root@localhost ~]# bash mail.sh                                                                  

Shell条件判断与流控匹配_第1张图片​​​​​​​ 

三、模式匹配case

case是一种条件语句,用于根据不同的条件执行不同的命令或操作

1. case语法结构

case <变量> in
  <模式1>)
    命令1
    ;;
  <模式2>)
    命令2
    ;;
  <模式3>)
    命令3
    ;;
  *)
    默认命令
    ;;
esac

2. 模式匹配示例

示例1:邀请用户输入待删除用户名,询问用户,确定要继续删除吗 yes/no

#!/bin/bash
read -p "请输入删除的用户名: " user
read -p "确认删除吗?[yes/no] " action
case "$action" in
Y|y|YES|yes|Yes|YeS|YEs)      #或者写成[yY]|[yY][eE][sS])
userdel -r $user
echo "$user已删除"
;;
*)
echo "thank you"
;;
esac

示例2: 系统工具箱查看不同的系统信息

#!/bin/bash 
cat <

参考文献:Shell 语法——if else 详解_shell if else if语句格式-CSDN博客 

你可能感兴趣的:(if流控,case判断)