第四章·shell编程-条件表达式

条件表达式

介绍:

条件表达式,我们非常的常用,可以说,任何编程语言,都离不开条件表达式,但是每种变成语言的写法都不太一样,在shell中,有一种独特的写法。

条件测试语句

条件测试语句,我们又叫做test语句

格式 介绍
test 条件 常规判断命令 都支持
[[ 条件 ]] 支持运算符和正则的条件表达式 支持 > < -eq -le -ne
[ 条件 ] 常用条件表达式 不支持 > < 支持:-eq -le -ne

文件表达式

表达式 含义 举例
-d 判断目录是否存在 test -d /etc
-f 判断文件是否存在 test -f /hosts
-e 判断是否存在 test -e /etc
-r 判断文件是否存在,并且有read权限 test -r /hosts
-w 判断文件是否存在,并且有write权限 test -w /etc
-x 判断文件是否存在,并且有execute权限 test -x /bin/ls
-s 判断文件是否存在,并且size是否大于0 test -s /etc/passwd
-L 判断文件是否存在,并且是否是软链接文件 test -L /bin
file1 -nt file2 file1是否比file2更新,newer than test 1.txt -nt 2.txt
file1 -ot file2 file1是否比file2更旧,older than test 1.txt -ot 2.txt
# 1.判断目录是否存在
[root@zabbix01 ~]# test -d /etc && echo '存在' || '不存在'
存在
[root@zabbix01 ~]# [ -d /etc ] && echo '存在' || '不存在'
存在
[root@zabbix01 ~]# [[ -d /etc ]] && echo '存在' || '不存在'
存在

# 2.判断文件是否存在
[root@zabbix01 ~]# [[ -f /etc/hosts ]] && echo '存在' || echo '不存在'
存在
[root@zabbix01 ~]# [ -f /etc/hosts ] && echo '存在' || echo '不存在'
存在
[root@zabbix01 ~]# test -f /etc/hosts && echo '存在' || echo '不存在'
存在

# 3.判断是否存在,不区分目录或文件
[root@zabbix01 ~]# test -e /etc/hosts && echo '存在' || echo '不存在'
存在
[root@zabbix01 ~]# [ -e /etc/hosts ] && echo '存在' || echo '不存在'
存在
[root@zabbix01 ~]# [[ -e /etc/hosts ]] && echo '存在' || echo '不存在'
存在

# 4.判断权限,注意如果是root用户,只能判断出来执行权限,使用普通用户即可
[root@zabbix01 ~]# ll /etc/shadow
---------- 1 root root 791 Aug 17 19:57 /etc/shadow
[root@zabbix01 ~]# [ -x /etc/shadow ] && echo '存在' || echo '不存在'
不存在
[root@zabbix01 ~]# [ -r /etc/shadow ] && echo '存在' || echo '不存在'
存在
[root@zabbix01 ~]# [ -w /etc/shadow ] && echo '存在' || echo '不存在'
存在

# 5.判断文件是否为空
[root@zabbix01 ~]# echo 123 >1.txt
[root@zabbix01 ~]# touch 2.txt
[root@zabbix01 ~]# [ -s 1.txt ] && echo '不为空' || echo '空文件'
不为空
[root@zabbix01 ~]# [ -s 2.txt ] && echo '不为空' || echo '空文件'
空文件

# 6.判断文件是否是软链接文件
[root@zabbix01 ~]# [ -L /bin ] && echo '软链接' || echo '非软链接'
软链接

# 7.判断文件新或旧 (修改时间)
[root@zabbix01 ~]# [ 1.txt -nt 2.txt ] && echo '1.txt比2.txt更新' || echo '2.txt比1.txt更新'
2.txt比1.txt更新
[root@zabbix01 ~]# [ 1.txt -ot 2.txt ] && echo '1.txt比2.txt更旧' || echo '2.txt比1.txt更旧'
1.txt比2.txt更旧

## 条件表达式使用格式
[ 条件 ] && cmd

[ 条件 ] && {
cmd1
cmd2
}

小练习:计算器

需求

1.首先要传递2个参数(数字)
2.传少了报错
 报错信息:至少传递两个整数...
3.传的不是数字报错
 报错信息:请输入两个整数,不能是字母或特殊符号...
4.计算出传递两个数字的
        - +
        - -
        - *
        - /
        - %

只支持整型

#!/bin/bash
num1=$1
num2=$2

[ $# -ne 2 ] && {
    echo '请传递两个参数...'
    exit 10
} || {
    expr $num1 + $num2 &>/dev/null
    [ $? -ne 0 ] && {
        echo '请输入两个整数...'
        exit 2
    } || {
        [[ $num2 -eq 0 ]] && {
            echo '除数不能为0...'
        } || {
            echo "$num1 + $num2 = `expr $num1 + $num2`"
            echo "$num1 - $num2 = `expr $num1 - $num2`"
            echo "$num1 x $num2 = `expr $num1 \* $num2`"
            echo "$num1 ÷ $num2 = `expr $num1 / $num2`"
            echo "$num1 % $num2 = `expr $num1 % $num2`"
        }
    }
}

支持浮点型

num1=$1
num2=$2

[ $# -eq 2 ] && {
    [[ $num1 =~ ^[0-9]+$|^[0-9]+\.[0-9]+$ ]] && [[ $num2 =~ ^[0-9]+$|^[0-9]+\.[0-9]+$ ]] && {
        [ $num2 != '0' ] && {
            echo "$num1 + $num2 = `awk -v a=$num1 -v b=$num2 'BEGIN{print a + b}'`"
            echo "$num1 - $num2 = `awk -v a=$num1 -v b=$num2 'BEGIN{print a - b}'`"
            echo "$num1 x $num2 = `awk -v a=$num1 -v b=$num2 'BEGIN{print a * b}'`"
            echo "$num1 ÷ $num2 = `awk -v a=$num1 -v b=$num2 'BEGIN{print a / b}'`"
            echo "$num1 % $num2 = `awk -v a=$num1 -v b=$num2 'BEGIN{print a % b}'`"
        } || {
            echo '除数不能为0...'
        }
    } || {
        echo '不能输入字母或特殊符号...'
    }
} || {
    echo '请输入两个参数...'
}

字符串表达式

表达式 含义 举例
-n not null 非空则成立 test -n 'lw'
-z null 空则成立 test -z 'lw'
"str1"="str2" 等号左边字符串与右边字符串相等则成立 test 'lw' = 'rowey'
"str1"!="str2" 等号左边字符串与右边字符串不等则成立 test 'lw' !='rowey'
-n:判断字符串是否为空,非空则成立
root@m01,172.16.1.61:~ # abc=''
root@m01,172.16.1.61:~ # test -n "$abc" && echo '字符串不为空' || echo '字符串为空'
字符串为空

root@m01,172.16.1.61:~ # abc='abc'
root@m01,172.16.1.61:~ # test -n "$abc" && echo '字符串不为空' || echo '字符串为空'
字符串不为空

-z:判断字符串是否为空,空则成立
root@m01,172.16.1.61:~ # abc='abc'
root@m01,172.16.1.61:~ # test -z "$abc" && echo '字符串为空' || echo '字符串不为空'
字符串不为空
root@m01,172.16.1.61:~ # abc=''
root@m01,172.16.1.61:~ # test -z "$abc" && echo '字符串为空' || echo '字符串不为空'
字符串为空
'str1' = 'str2':字符串相等则成立
root@m01,172.16.1.61:~ # test 'abc' = 'abc' && echo '字符串相等' || echo '字符串不相等'
字符串相等
root@m01,172.16.1.61:~ # test 'abc' = 'abc1' && echo '字符串相等' || echo '字符串不相等'
字符串不相等
'str1' != 'str2':字符串不相等则成立
root@m01,172.16.1.61:~ # test 'abc' != 'abc' && echo '字符串不相等' || echo '字符串相等'
字符串相等
root@m01,172.16.1.61:~ # test 'abc' != 'abc1' && echo '字符串不相等' || echo '字符串相等'
字符串不相等

整数表达式

整数表达式介绍

表达式 含义 test举例 [[]]举例
-eq equal 等于 test 2 -eq 2 [[ 2 == 2 ]]
-ne not equal 不等于 test 2 -ne 2 [[ 2 != 2 ]]
-gt great than 大于 test 2 -gt 2 [[ 2 > 2 ]]
-ge great equal 大于等于 test 2 -ge 2 [[ 2 >=2 ]]
-lt less than 小于 test 2 -lt 2 [[ 2 < 2 ]]
-le less equal 小于等于 test 2 -le 2 [[ 2 <= 2 ]]

注意:当[[]] 遇到大于,基本就歇菜了,需要使用转译符,那么系统就推荐使用-ge,-gt这样的方式,如果使用这样的方式,那莫不如就用[]


[root@zabbix01 script]# [[ 18 >= 16 ]] && echo 1 || echo 2
-bash: syntax error in conditional expression
-bash: syntax error near `16'
[root@zabbix01 script]# [[ 18 \>= 16 ]] && echo 1 || echo 2
-bash: conditional binary operator expected
-bash: syntax error near `\>='
[root@zabbix01 script]# [[ 18\>= 16 ]] && echo 1 || echo 2
-bash: conditional binary operator expected
-bash: syntax error near `16'
[root@zabbix01 script]# [[ 18\>=16 ]] && echo 1 || echo 2
1
{1}
[root@zabbix01 script]# [[ 18 -ge 16 ]] && echo 1 || echo 2
1
[root@zabbix01 script]# [ 18 -ge 16 ] && echo 1 || echo 2
1
{1}
## 不要在[]中使用>和<,能不能使用呢?也能但是又坑
[root@zabbix01 script]# age=30
[root@zabbix01 script]# [ $age > 20 ] && echo '真' || echo '假'
真
[root@zabbix01 script]# [ $age > 50 ] && echo '真' || echo '假'
真
{1}
## 这里把>当成了重定向
[root@zabbix01 script]# ll
-rw-r--r-- 1 root root   0 Aug 31 17:04 20
-rw-r--r-- 1 root root   0 Aug 31 17:04 50
{1}
## 那么应该怎么用?转义符
[root@zabbix01 script]# age=30
[root@zabbix01 script]# [ $age \> 50 ] && echo '真' || echo '假'
假
[root@zabbix01 script]# [ $age \> 10 ] && echo '真' || echo '假'
真
{1}
## 还是有坑,为啥呢。再举个例子
[root@zabbix01 script]# age=2
[root@zabbix01 script]# echo $age
2
[root@zabbix01 script]# [ $age \> 19 ] && echo '真' || echo '假'
真
{1}
## 为啥还是真呢?因为这个时候做大小比较的时候,按照字符串根据ASCII中的排序
[root@zabbix01 script]# seq 20|sort
1
10
11
12
13
14
15
16
17
18
19
2
20
3
4
5
6
7
8
9
{1}

所以,两个中括号是不是一无是处呢?之前我们说,他们可以使用正则。

[[]]的成员运算

举几个例子就明白了。

# 1.判断变量中是否包含18
[root@zabbix01 script]# [[ $name =~ 18 ]] && echo '有18' || echo '木有18'
有18

# 2.判断变量中是否有数字
[root@zabbix01 script]# [[ $name =~ [0-9] ]] && echo '有数字' || echo '木有数字'
有数字

# 3.判断变量是否只有数字
## 方法一: expr
## 方法二:
[root@zabbix01 script]# name=6
[root@zabbix01 script]# [[ $name =~ ^[0-9]$ ]] && echo '只有数字' || echo '木有数字'
只有数字

## 但是如果这样,只能匹配一个数字
[root@zabbix01 script]# name=66
[root@zabbix01 script]# [[ $name =~ ^[0-9]$ ]] && echo '只有数字' || echo '木有数字'
木有数字

## 那么我们就得再加一个
[root@zabbix01 script]# [[ $name =~ ^[0-9][0-9]$ ]] && echo '只有数字' || echo '木有数字'
只有数字

## 然鹅,我们并不知道用户会传递多少位的数字啊。
## 于是我们需要使用正则表达式中的,+ 如果放在数字后面,代表连续的数字
[root@zabbix01 script]# [[ $name =~ ^[0-9]+$ ]] && echo '只有数字' || echo '木有数字'
只有数字

逻辑运算表达式

逻辑运算表达式介绍

表达式 含义 符号
! 非,取反 !
&& && -a
|| || -o

and条件

只有都为真,条件才为真,条件中有任何一个为假,那么结果就是假

条件1 条件2 结果

or条件

只要有一个为真,结果就是真,除非两个都为假,结果才是假。

条件1 条件2 结果

shell练习

企业面试题1

命令行中输入一个数字,如果数字是1,则输出1,如果是2则输出2,既不是1也不是2则显示脚本使用方法,并退出程序

#方法一:
num=$1
[ $num -eq 1 -o $num -eq 2 ] && echo $num || echo "Usage: $0 {1|2}"

#方法二:
num=$1
[[ $num =~ ^[1-2]$ ]] && echo "$num" || echo "Usage: $0 {1|2}"

#方法三:
num=$1
if [ $num -eq 1 -o $num -eq 2 ];then
echo $num
else
echo "Usage: $0 {1|2}"
fi

山林不向四季起誓 荣枯随缘