条件判断

发布时间 2023-12-20 17:24:24作者: Mrterrific

我们目前写的shell脚本都是按照顺序,自上而下的,依次读取命令,且执行。

但是如果你要控制程序的执行顺序,修改这个顺序,那就得对脚本进行逻辑控制。

那么就必须得进行条件判断了。

坑记录。

1.务必注意,语法,中括号,条件测试符号左右两边的空格,别漏了。

2.条件判断里,关于变量是否添加双引号、本质上不一样的。。。。

 

0.学前预览

先看下,系统自带的脚本,shell的语法,在你学习了之后,就看得懂了,也可以模仿着写。

 

系统自带脚本

shell字符串变量的子串功能,用的极少,因为shell字符串变量本身处理起来,不太方便,看看语法就行。


关于字符串子串的功能,建议以后去学python再去体验子串的强大。

 

1.基于文件进行条件判断

我们这里先来学习这个条件判断的语法,下一步才进入if语句的学习。

常用参数

参数解释举例
-e 文件或目录存在就是true [ -e filepath ]
-s 文件存在且只要有一个字母就是true [ -s filepath ]
-f 文件存在且是普通文件类型就是true [ -f filepath ]
-d 文件存在且是目录类型就是true [ -d filepath ]
-r 文件存在且有read权限就是true [ -r filepath ]
-w 文件存在且有write权限就是true [ -w filepath ]
-x 文件存在且有x权限就是true [ -x filepath ]
-- -- --
-- -- --

更多参数

做好笔记即可,看来回来查查

test 命令最短的定义可能是评估一个表达式;如果条件为真,则返回一个 0 值。如果表达式不为真,则返回一个大于 0 的值 — 也可以将其称为假值。检查最后所执行命令的状态的最简便方法是使用 $? 值。

参数:

1. 关于某个文件名的『类型』侦测(存在与否),如 test -e filename 

-e 该『文件名』是否存在?(常用) 
-f 该『文件名』是否为文件(file)?(常用) 
-d 该『文件名』是否为目录(directory)?(常用) 
-b 该『文件名』是否为一个 block device 装置? 
-c 该『文件名』是否为一个 character device 装置? 
-S 该『文件名』是否为一个 Socket 文件? 
-p 该『文件名』是否为一个 FIFO (pipe) 文件? 
-L 该『文件名』是否为一个连结档? 

2. 关于文件的权限侦测,如 test -r filename 

-r 侦测该文件名是否具有『可读』的属性? 
-w 侦测该文件名是否具有『可写』的属性? 
-x 侦测该文件名是否具有『可执行』的属性? 
-u 侦测该文件名是否具有『SUID』的属性? 
-g 侦测该文件名是否具有『SGID』的属性? 
-k 侦测该文件名是否具有『Sticky bit』的属性? 
-s 侦测该文件名是否为『非空白文件』? 

3. 两个文件之间的比较,如: test file1 -nt file2 

-nt (newer than)判断 file1 是否比 file2 新 
-ot (older than)判断 file1 是否比 file2 旧 
-ef 判断 file2 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩! 

4. 关于两个整数之间的判定,例如 test n1 -eq n2 

-eq 两数值相等 (equal) 
-ne 两数值不等 (not equal) 
-gt n1 大于 n2 (greater than) 
-lt n1 小于 n2 (less than) 
-ge n1 大于等于 n2 (greater than or equal) 
-le n1 小于等于 n2 (less than or equal) 

5. 判定字符串的数据 

test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true 
test -n string 判定字符串是否非为 0 ?若 string 为空字符串,则为 false。
注: -n 亦可省略 
test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true 
test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false 

6. 多重条件判定,例如: test -r filename -a -x filename 

-a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。 
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。 
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true

结合test命令

写法1

test 条件语句

为真
[root@yuchaoit666 ~/p3-shell]#touch yuchaoit.log
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#test -f "yuchaoit.log" && echo "true" || echo "false"
true


为假
[root@yuchaoit666 ~/p3-shell]#test -f "666yuchaoit.log" && echo "true" || echo "false"
false

写法2

[ 条件语句 ]

[root@yuchaoit666 ~/p3-shell]#[ -f "666yuchaoit.log" ] && echo "true" || echo "false"
false
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#
[root@yuchaoit666 ~/p3-shell]#[ -f "yuchaoit.log" ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~/p3-shell]#

测试常用条件参数

俩写法

1.判断ansible的主机清单文件是否存在,不存在提示用户先创建再使用ansible命令。

----------------------------------------------------------------------------------


# 普通文件
[ -f /etc/ansible/hosts ] && echo "主机清单hosts文件存在..."  || echo "先去创建主机清单hsots文件!!"

----------------------------------------------------------------------------------


# 文件存在
[ -e /etc/ansible/hosts ] && echo "主机清单hosts文件存在..."  || echo "先去创建主机清单hsots文件!!"

----------------------------------------------------------------------------------



# 注意坑,root怕你这权限吗?
[ -r /etc/ansible/hosts ] && echo "主机清单hosts允许读取!!"  || echo "无权读取!!"

[ -w /etc/ansible/hosts ] && echo "主机清单hosts允许写入!!"  || echo "无权写入!!"

[ -x /etc/ansible/hosts ] && echo "主机清单hosts允许执行!!"  || echo "无权执行!!"
----------------------------------------------------------------------------------



# 文件里有内容吗?
# 试试
>/etc/ansible/hosts
# 条件判断
[ -s /etc/ansible/hosts ] && echo "hosts清单文件有内容!!"  || echo "hosts文件为空,请写入!!"

----------------------------------------------------------------------------------



几个特殊文件,看看有内容吗
root@yuchaoit666 ~/p3-shell]#[ -s /dev/zero ] && echo true || echo false
false

[root@yuchaoit666 ~/p3-shell]#[ -s /dev/null ] && echo true || echo false
false

[root@yuchaoit666 ~/p3-shell]#[ -s /etc/passwd ] && echo true || echo false
true


----------------------------------------------------------------------------------
test命令写法
[root@yuchaoit666 ~/p3-shell]#test -s /etc/passwd  && echo true || echo false
true

[root@yuchaoit666 ~/p3-shell]#test -s /etc/passwddddd  && echo true || echo false
false

2.基于整数判断

条件语法

-eq 两数值相等 (equal) 
-ne 两数值不等 (not equal) 
-gt n1 大于 n2 (greater than) 
-lt n1 小于 n2 (less than) 
-ge n1 大于等于 n2 (greater than or equal) 
-le n1 小于等于 n2 (less than or equal)

案例

猜数字比大小

猜数字大小程序开发(初版,还有很多bug!一步步优化!)


cat > num.sh<<'EOF'
# 结果
result=18
# 用户输入
read -p "请输入数字,猜大小:" num

if [ $result -eq $num ];then
    echo "猜对啦!你可真nb!"
elif [ $result -gt $num ];then
    echo "太小了,再猜!"
elif [ $result -lt $num ];then
    echo "太大了,再猜!"
fi
EOF

执行

 

比较数字大小,美化结果

cat > beautiful_num.sh<<'EOF'
# 加载美化脚本
source /etc/init.d/functions

# 接收输入
read -p "please input num1:" num1
read -p "please input num2:" num2


# 条件判断测试
# 等于
[ $num1 -eq $num2 ] && action "-eq 等于OK" /bin/true || action "-eq NO" /bin/false

# 不等于
[ $num1 -ne $num2 ] && action "-ne 不等于OK" /bin/true || action "-ne NO" /bin/false

# 大于
[ $num1 -gt $num2 ] && action "-gt 大于OK" /bin/true || action "-gt NO" /bin/false

# 小于
[ $num1 -lt $num2 ] && action "-lt 小于OK" /bin/true || action "-lt NO" /bin/false

# 大于等于
[ $num1 -ge $num2 ] && action "-ge 大于等于OK" /bin/true || action "-ge NO" /bin/false

# 小于等于
[ $num1 -le $num2 ] && action "-le 小于等于OK" /bin/true || action "-le NO" /bin/false
EOF

练习题

判断整数

# 1.判断用户输入是否是整数(提示,正则过滤)

cat >check_num.sh<<'EOF'
#!/bin/bash
# 用户输入
read -p "please input your num:" num

# 正则过滤出连续的非数字
check_res=$(echo $num|grep -E '[^0-9]+'|wc -l)

# 只要为零,表示是纯数字
[ $check_res -eq 0 ] && echo -e "输入整数正确,输入结果是:\033[43;30m ${num} \033[0m" || echo  -e "我真是服了,让你输入的是数字!!,你输入的 \033[43;30m ${num} \033[0m 这是什么玩意?"
EOF

 

方法2

if [ -z "$(echo $your_num|sed -rn '/^[0-9]+$/p')"  ];then
           echo "请输入纯数字整数!"
        continue
fi

判断参数个数

# 2. 限制用输入的参数必须是2个、

cat > check_vars.sh <<'EOF'
#!/bin/bash
[ $# -ne 2 ] && echo "只能输入2个参数!!" || echo -e "参数1:$1\n参数2:$2"
EOF

 

判断用户的密码是否符合6位

方案1:利用变量的子字符串功能,判断字符串长度${#变量}

cat > user_pwd.sh<<'EOF'
read  -p "please input your pwd:" pwd

# 条件判断处理,利用变量的子字符串功能
[ ${#pwd} -ne 6 ] && echo "错误!密码必须是6位" || echo "正确!您的密码是:${pwd}"
EOF

方案2:使用wc -L 参数

cat > pwd.sh <<'EOF'
read -p "please input your pwd:" pwd

# 密码长度校验
pwd_len=$(echo $pwd|wc -L)
[ $pwd_len -ne 6 ] && echo "错误!密码必须是6位" || echo "正确!您的密码是:${pwd}"
EOF

3.基于字符串判断

语法

参数解释案例
== 两边值相等为true [ "$a" == "$b" ]
!= 两边值不等为true [ "$a" != "$b" ]
-z 字符串为空时为true [ -z "$a" ]
-n 字符串内容不为空为true [ -n "$a" ]
= 同 == 作用一样 [ "$a" = "$b" ]

系统自带脚本参考

 

以及一段关于mysql的脚本

233       # pid-file exists, the server process doesn't.
234       # it must've crashed, and mysqld_safe will restart it
235       if test -n "$crash_protection"; then
236         crash_protection=""
237         sleep 5
238         continue  # Check again.
239       fi

这里就是判断,当该crash_protection变量非空时,将其置空

这里的逻辑我们不用过多关注,从注释可以得知

该代码作用是,当mysql的pid-file存在,但是mysql进程不存在,这就证明mysql异常挂掉了,mysql应该重启。

练习

简单等于、不等于符号

[root@yuchaoit666 ~]#[ 10 == 10 ] && echo "yes" || echo "no"
yes
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 10 != 10 ] && echo "yes" || echo "no"
no
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 10 != 5 ] && echo "yes" || echo "no"
yes

条件参数-z和-n相反测试

[root@yuchaoit666 ~]#name="yuchao666"
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
# -z 字符串为空,才为真
[root@yuchaoit666 ~]#[ -z $name ] && echo "true" || echo "false"
false
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ -z $name2 ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ -n $name ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ -n $name2 ] && echo "true" || echo "false"
true
[root@yuchaoit666 ~]#

模拟开发登录程序

接收用户输入,和密码文件对比,判断是否登录成功。

现有账号密码
yuchao01
chaoge666
cat >user_login.sh<<'EOF'
read -p "please input username:" username
read -p "please input pwd:" pwd

[ $username == "yuchao01" -a $pwd == "chaoge666" ] && echo "登录成功" || echo "账号密码错误" 
EOF

4. 逻辑操作符

逻辑运算,也就是生活里的 真、假概念

! 取反,也就是结果相反的值

-a 是“与”的意思(等同 && 和and),要求,左右两个逻辑值都为真,结果才为真,否则为假

-o 是或者的意思,(or 和 ||),左右两个逻辑,只要有一个真,结果就为真

结果为真,对应计算机数字是1

结果为假,计算机数字为0

注意:选用不同的语法,对应的测试符号不一样!!!
参数解释案例
-a 左右两边条件同时为真时,为true [ 6 -eq 6 -a 8 -gt 3 ]
-o 左右两边条件有一个为真,就为true [ 1 -gt 1 -o 2 -eq 2 ]
! 结果取反  
   
结果取反
[root@yuchaoit666 ~]#[ 1 -eq 1 ] && echo true || echo false
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ !  1 -eq 1 ] && echo true || echo false
false


或运算
[root@yuchaoit666 ~]#[ 1 -eq 1 -o 2 -gt 2 ] && echo yes || echo no
yes
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 1 -gt 1 -o 2 -gt 2 ] && echo yes || echo no
no
[root@yuchaoit666 ~]#[ 1 -gt 1 -o 2 -lt 2 ] && echo yes || echo no
no
[root@yuchaoit666 ~]#[ 1 -gt 1 -o 2 -eq 2 ] && echo yes || echo no
yes


并且运算
[root@yuchaoit666 ~]#[ 6 -eq 6 -a 8 -gt 3 ] && echo true || echo no
true
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#
[root@yuchaoit666 ~]#[ 6 -eq 6 -a 8 -lt 3 ] && echo true || echo no
no