一、shell条件测试
1.1 用途
- 为了能够正确出来shell程序运行过程中遇到的各种情况,Linux shell提供了一组测试运算符。
- 通过这些运算符,shell程序能够判断某种或者几个条件是否成立。
- 条件测试在各种流程控制语句,例如判断语句和循环语句中发挥了重要作用,所以了解和掌握这些条件测试时非常重要的
1.2 基本语法
1.2.1 格式:
格式1:test -参数 条件表达式
格式2:[ 条件表达式 ] #注意:[] 的左右要有空格
格式3:[ [ 条件表达式 ] ] #注意:[ ] 的左右要有空格
格式4:((条件表达式))
- test单独使用,判断条件为真,echo $?返回0,假返回1
- test 与 [ ] 等价
- [ [ ] ]是扩展命令,可以使用通配符等进行模式匹配,&& || > < 等操作符可以直接应用于双括号中,但不能用于但中括号中
- (()) 一般用于if语句里,两端不需要有空格,测试对象为整数
1.3示例
test 语法
[root@server ~]# test -f /etc/passwd #-f 表示文件是否存在
[root@server ~]# echo $?
0
[root@server ~]# test -f /a1.txt #利用状态码表示,0成立、1不成立
[root@server ~]# echo $?
1
[root@server ~]# test -f /etc/passwd && echo 1 || echo 0 #1成立,0不成立
[root@server ~]# [ -f /etc/passwd ] #注意要加空格
[root@server ~]# echo $?
0
[root@server ~]# [ -f /etc/passwd ] && echo 1 || echo 0
1
[root@server ~]# [ -f /etc/222 ] && echo 1 || echo 0
0
[ [ ] ] 语法,注意空格
[root@server ~]# [[ 3 > 2 && 1 > 2 ]] && echo 1 || echo 0
0
[root@server ~]# [[ 3 > 2 || 1 > 2 ]] && echo 1 || echo 0
1
#(()) 语法
[root@server ~]# ((3>5)) && echo 1 || echo 0
0
[root@server ~]# ((9>5)) && echo 1 || echo 0
1
[root@server ~]# ((9.5>5)) && echo 1 || echo 0
-bash: ((: 9.5>5: syntax error: invalid arithmetic operator (error token is ".5>5")
0
[root@server ~]#
1.4文件测试
1.4.1 参数:
常用的文件测试操作符 | 说明 |
---|---|
-a/-e 文件 | 文件是否存在 |
-b 文件 | 文件是否存在,且为块文件,如果文件存在且是一个块文件,则结果为0 |
-c 文件 | 文件是否存在且为字符文件,如果文件存在且是一个字符文件,则结果为0 |
-L 文件 | 文件存在且为链接文件则为真 |
-d 文件 | 文件存在且为目录则为真,即测试表达式成立 |
-f 文件 | 文件存在且为普通文件则为真,即测试表达式成立 |
-s 文件 | 文件存在且文件大小不为0则为真 |
-u 文件 | 文件是否设置suid位,如果设置了suid,则结果为0 |
-r 文件 | 文件存在且可读为真 |
-w 文件 | 文件存在且可写为真 |
-x 文件 | 文件存在且可执行则为真 |
f1 -nt f2,nt为newer than | 文件f1比文件f2新则为真,根据文件的修改时间来计算 |
f1 -ot f2,ot为older than | 文件f1比文件f2旧则为真,根据文件的修改时间来计算 |
1.4.2 例
[root@server ~]# [ -d /root ] && echo yes || echo no
yes
[root@server ~]# [ -d /dev/nvme0n1 ] && echo yes || echo no
no
[root@server ~]# [ -b /dev/nvme0n1 ] && echo yes || echo no
yes
[root@server ~]# [ -L /dev/cdrom ] && echo yes || echo no
yes
[root@server ~]# [ -e /file1 ] && echo yes || echo no
no
1.编写脚本,测试文件是否存在,不存在则创建
[root@server ~]# vim test6.sh
#!/bin/bash
FILE=$1
echo $FILE
if test -e $FILE
then
echo "$FILE exists and it is a normal file"
else
echo "$FILE doesn't exit!!"
echo "create file $FILE aumtomatically"
touch $FILE
fi
[root@server ~]# bash test6.sh
exists and it is a normal file
[root@server ~]# bash test6.sh /etc/passwd
/etc/passwd
/etc/passwd exists and it is a normal file
[root@server ~]# bash test6.sh /file2.txt
/file2.txt
/file2.txt doesn't exit!!
create file /file2.txt aumtomatically
[root@server ~]# ls /
111 dev helen nfsfile sbin usr
a etc home opt scripts var
afs etc.tar.gz lib proc srv
bin file lib64 pub sys
boot file2.txt media root test
day04 file.txt mnt run tmp
1.5 整数的测试
1.5.1 作用
- 用于比较两个数值的大小关系,操作的对象是数值
1.5.2 操作符
在[]以及test中使用的比较符号 | 在(())和[[]]中使用的比较符号 | 说明 |
---|---|---|
-eq | ==或= | 相等,全拼为equal |
-ne | != | 不相等,全拼为not equal |
-gt | > | 大于,全拼为greater than |
-ge | >= | 大于等于,全拼为greater equal |
-lt | < | 小于,全拼为less than |
-le | <= | 小于等于,全拼为less equal |
1.5.3 例:
[root@server ~]# [ 5 -gt 3 ] && echo yes || echo no
yes
[root@server ~]# test "2" -lt "1" && echo yes || echo nono
[root@server ~]# ((5>3)) && echo yes || echo no
yes
#知识代码
#检查左侧内容是否匹配右侧的正则表达式,=~ 正则表达n1的值是否包含数字
[root@server ~]# n1=123
[root@server ~]# [[ "$n1" =~ ^[0-9]+$ ]] && echo y || echo n
y
[root@server ~]# n1="china"
[root@server ~]# [[ "$n1" =~ ^[0-9]+$ ]] && echo y || echo n
n
#系统用户小于50则输出信息
[root@server ~]# [ $(cat /etc/passwd | wc -l) -lt 50 ] && echo "用户数小于50" || echo "用户数超过50"
用户数超过50
1.6 逻辑操作符
1.6.1 符号
在[]中使用的逻辑操作符 | 在test、[[]]和(())中使用的逻辑操作符 | 说明 |
---|---|---|
-a | && | and,与,两端都为真,则结果为真 |
-o | || | or,或,两端有一个为真,则结果为真 |
! | ! | not,非,两端相反,则结果为真 |
1.6.2 例:
[root@server ~]# [ -f /etc/passwd -a -f /etc/services ] && echo yes || echo no
yes
#-a 左侧测试是否为普通文件, 右侧测试是否为普通文件,若条件成立则输出yes 否则输出no
[root@server ~]# [[ -f /etc/hosts && -f /etc/services ]] && echo yes || echo no
yes
[[]] 中使用 &&
1.7 命令分隔符
1. cmd1;cmd2 以独立的进程依次进行cmd1 和 cmd2
(cmd1;cmd2) 在同一进程中依次执行cmd1和cmd2
cmd1&cmd2 cmd1 和cmd2 同时执行,分属于不同进程
cmd1&&cmd2 当cmd1为真时,则执行cmd2
cmd1||cmd2 当cmd1不为真时,则执行cmd2
cmd& 后台执行
#如果账户fox10不存在,则添加该账户
[root@server ~]# id fox10
id: ‘fox10’: no such user
[root@server ~]# id fox10 &> /dev/null && echo "fox10 is exits" || useradd fox10
[root@server ~]# id fox10
uid=10124(fox10) gid=10124(fox10) groups=10124(fox10)
#&> /dev/null 将左侧的正确和错误的输出转向到"黑洞"
1.8 案例分析
- 例1:判断当前以登陆的账户数,超过5个,从输出"too many"
[root@server ~]# num=$(who | cut -d " " -f1 | sort -u |wc -l)
[root@server ~]# [ $num -gt 5 ] && echo "too many"
[root@server ~]#
#who : 查看当前已登录的账户信息
#cut -d " " -f1 :以空格作为切割依据,截取第一列信息
#sort -u :去重后排序
#wc -l :统计行数
- 例2:取出 /etc/passwd 文件的第六行
[root@server ~]# head -6 /etc/passwd | tail -1
sync:x:5:0:sync:/sbin:/bin/sync
#法2:
[root@server ~]# sed -n 6p /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
- 例3:如果/var/log/messages 文件下的行数大于50行
[root@server ~]# (($(cat /var/log/messages | wc -l) > 50)) && echo "文件好大" || echo "还行"
文件好大
- 例4:编写一个脚本mkf.sh ,功能:显示root目录下的文件信息,之后建立一个aa目录,在aa目录中新建一个文件bb.txt,并修改该文件权限为可执行
、
[root@server ~]# vim mkf.sh
#!/bin/bash
ls -l /root
mkdir /root/aa
touch /root/aa/bb.txt
chmod a+x /root/aa/bb.txt
[root@server ~]# bash mkf.sh
- 例7:编写一个脚本test7.sh,程序从键盘读入一个目录名,判断该目录是否存在,不存在则创建,并显示目录信息
法1 :
[root@server ~]# vim test7.sh
#!/bin/bash
read -p "请输入目录名称:" FILE
if test -e $FILE
then
echo "文件存在"
else
echo "文件不存在,创建文件"
touch $FILE
fi
[root@server ~]# bash test7.sh
请输入目录名称:2222
文件不存在,创建文件
[root@server ~]# ls
111 Bing.txt mkf.sh
2222 case.sh Music
2.sh d mysql_backup_715.sh
333 date passwd
99.sh Desktop Pictures
法2:
[root@server ~]# vim test7.sh
#!/bin/bash
read -p "请输入目录名称:" dir
[ -d $dir ] && ls -l $dir || (echo "目录不存在,开始新建目录"; mkdir $dir ; ls -l $dir)
[root@server ~]# bash test7.sh
请输入目录名称:11111
目录不存在,开始新建目录
total 0
[root@server ~]# ll
total 96
drwxr-xr-x. 2 root root 6 Apr 20 09:47 111
drwxr-xr-x 2 root root 6 Jul 21 18:57 11111
- 例6:编写脚本test8.sh ,从键盘读入x,y的值计算后输出结果
[root@server ~]# vim test8.sh
#!/bin/bash
read -p "请输入x的值:" x
read -p "请输入y的值:" y
if [ -n "$x" -a -n "$y" ]
then
if [[ "$x" =~ ^[0-9]$ ]] && [[ "$y" =~ ^[0-9]$ ]]
then
sum=$[x+y]
echo "$x+$y=$sum"
else
echo "请输入数字"
fi
else
echo "请输入有效内容"
fi
[root@server ~]# bash test8.sh
请输入x的值:2
请输入y的值:3
2+3=5
[root@server ~]# bash test8.sh
请输入x的值:
请输入y的值:
请输入有效内容
- 例7:编写脚本test9.sh,显示所有用户,选择一个用户名输入,若id为0 则为管理员,否则为普通账户
[root@server ~]# vim test9.sh
#!/bin/bash
cat /etc/passwd | cut -d ":" -f1 | sort -u
read -p "请输入一个账户名称:" us
[ $(id -u $us) -eq 0 ] && echo "此用户为管理员" || echo "此用户为普通账户"
[root@server ~]# bash test9.sh
- 例8 :编写脚本test10.sh,给定文件/etc/sos/sos.conf 判断是否有空白行,有则显示空白行的行数,否则显示没有空白行
[root@server ~]# vim test10.sh
#!/bin/bash
num=$(grep ^$ /etc/sos/sos.conf | wc -l)
if [ $num -gt 0 ];then
echo "含有空白行,行数为$num 行 "
grep -n ^$ /etc/sos/sos.conf
else
echo "此文件无空白行"
fi
[root@server ~]# bash test10.sh
含有空白行,行数为4 行
10:
17:
25:
32: