shell选择结构(if)

Posted 何翰宇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell选择结构(if)相关的知识,希望对你有一定的参考价值。

文章目录


一、条件判断

1. 语法格式

  • 格式1:test条件表达式
  • 格式2:[ 条件表达式 ]
  • 格式3:[[ 条件表达式 ]](支持在正则表达式)
    test的参数很多,可以用man命令查看

2. 条件判断相关参数

1)判断文件存在与否

-e	是否存在   不管是文件还是目录,只要存在,条件就成立
-f	是否为普通文件
-d	是否为目录
-S	socket
-p	pipe
-c	character
-b	block
-L	软link

三种语法格式:
 test -e file1	只要文件存在条件为真
 [ -d ~/tmp/files ]	判断目录是否存在,存在条件为真
 [ ! -d ~/tmp/files ]	判断目录是否存在,不存在条件为真
 [[ -f ~/tmp/file1 ]]	判断文件是否存在,并且是一个普通的文件

-s 判断文件是否有内容(大小),非空文件条件满足
说明:-s表示非空,! -s 表示空文件
说明:file1中是有内容的

[root@lamp tmp]# test -s file1
[root@lamp tmp]# echo $?
0
[root@lamp tmp]# touch temp
[root@lamp tmp]# cat temp
[root@lamp tmp]# test -s temp;echo $?
1
[root@lamp tmp]# test ! -s temp;echo $?
0
[root@lamp tmp]# echo $?
0
[root@lamp tmp]# test ! -s file1;echo $?
1

2)文件权限相关的判断

-r	当前用户对其是否可读
-w	当前用户对其是否可写
-x	当前用户对其是否可执行
-u	是否有suid
-g	是否sgid
-k	是否有t位

3)两个文件的比较判断

file1 -nt  file2	比较file1是否比file2新	
file1 -ot  file2 	比较file1是否比file2旧
file1 -ef  file2	比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode

test file1 -nt file2	
[ file1 -ot file2 ]
[root@lamp tmp]# ll
total 4
-rw-r--r-- 1 root root 12 Aug  3 19:10 file1
-rw-r--r-- 1 root root  0 Aug  3 19:17 file2
drwxr-xr-x 2 root root  6 Aug  3 18:51 files
-rw-r--r-- 1 root root  0 Aug  3 19:13 temp
[root@lamp tmp]# test file1 -nt file2;echo $? # 比较file1是否比file2新
1
[root@lamp tmp]# test file1 -ot file2;echo $? # 比较file1是否比file2旧
0
[root@lamp tmp]# [ file1 -ef feil2 ];echo $? # 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode
1

4)整数之间的判断

-eq	相等
-ne	不等
-gt	大于
-lt	小于
-ge   大于等于
-le	小于等于

5)字符串之间的判断

-z  是否为空字符串   		字符串长度为0,就成立
-n  是否为非空字符串    	只要字符串非空,就是成立
string1 = string2 		是否相等
string1 != string2 		不等

[root@lamp tmp]# str1=abc
[root@lamp tmp]# str2=qwer
[root@lamp tmp]# test -z $str1
[root@lamp tmp]# echo $?
1
[root@lamp tmp]# test -n $str1
[root@lamp tmp]# echo $?
0
[root@lamp tmp]# [ $str1 = $str2 ]
[root@lamp tmp]# echo $?
1
[root@lamp tmp]# [ $str1 != $str2 ];echo $?
0

6)多重条件判断

逻辑判断符号:

  • -a&& (and 逻辑与) 两个条件同时满足,整个大条件为真
  • -o|| (or 逻辑或) 两个条件满足任意一个,整个大条件为真
[ 1 -eq 1 -a 1 -ne 0 ]				整个表达式为真
[ 1 -eq 1 ] && [ 1 -ne 0 ]			


[ 1 -eq 1 -o 1 -ne 1 ]				整个表达式为真
[ 1 -eq 1 ] || [ 1 -ne 1 ]


[root@lamp tmp]# [ 1 -eq 0 ] && echo true || echo false
false
[root@lamp tmp]# [ 1 -eq 1 ] && echo true || echo false
true

&&:前面的表达式为真
||:前面的表达式为假



总结:
1、; && ||都可以用来分割命令或者表达式
2、; 完全不考虑前面的语句是否正确执行,都会执行;号后面的内容
3、&& 需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然
make && make install
4、|| 需要考虑||前面的语句的非正确性,前面语句执行错误才会执行||后的内容;反之亦然
5、如果&&和||一起出现,从左往右依次看,按照以上原则

一、流程控制语句

1. 基本语法结构

if

if [ 条件 ];then
		要执行的命令1
		要执行的命令...
fi

if+else

if [ 条件 ];then
		要执行的命令
	else
		要执行的命令
fi

if+elif+else

if [ 条件1 ];then
		要执行的命令1
	elif [ 条件2 ];then
		要执行的命令2
	else
		要执行的命令3
fi

#如果条件1满足,执行命令1后结束;
#如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;
#如果条件1和条件2都不满足执行命令3结束.

嵌套if+else

if [ 条件1 ];then
		要执行的命令
		if [ 条件2 ];then
			要执行的命令
		fi
		else
			if [ 条件3 ];then
				要执行的命令
			elif [ 条件4 ];then
				要执行的命令
			else
				要执行的命令
			fi
fi

#如果条件1满足,执行命令1;如果条件2也满足执行命令2,如果不满足就只执行命令1结束;
#如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;
#如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5

3. 示例

# 通过uid判断是否是root账号
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is admin"
the user is admin
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is not admin"
the user is not admin
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
the user is admin



[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is admin"
the user is admin
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is not admin"
the user is not admin
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
the user is admin
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is admin"
the user is admin
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is not admin"
the user is not admin
[root@lamp tmp]# [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
the user is admin

1)类C风格的数值比较

类似于C语言的比较方法
注意:在(( ))中,=表示赋值;==表示判断

[test@lamp tmp]$ ((1==2));echo $?
1
[test@lamp tmp]$ ((1<2));echo $?
0
[test@lamp tmp]$ ((1>=1));echo $?
0
[test@lamp tmp]$ ((`id -u`==0));echo $?
1
[test@lamp tmp]$ unset $a
[test@lamp tmp]$ ((a=123));echo $a
123
[test@lamp tmp]$ unset a
[test@lamp tmp]$ ((a==123));echo $?
1

2)字符串比较

注意:双引号引起来,看作一个整体;= 和 == 在 [ 字符串 ] 比较中都表示判断

[root@lamp tmp]# str="hello world";tmp="world"
[root@lamp tmp]# [ $str = $tmp ];echo $?
-bash: [: too many arguments
2
[root@lamp tmp]# [ "$str" = "$tmp" ];echo $?
1
[root@lamp tmp]# [ "$str" != "$tmp" ];echo $?
0
[root@lamp tmp]# [ "$str" !== "$tmp" ];echo $?
-bash: [: !==: binary operator expected
2
[root@lamp tmp]# [ "$str" == "$tmp" ];echo $?
1
[root@lamp tmp]# test "$str" != "$tmp";echo $?
0

2. 使用案例

1)判断当前主机是否和远程主机是否能ping通

  1. 使用哪个命令实现 ping -c
  2. 根据命令的执行结果状态来判断是否通 $?
  3. 根据逻辑和语法结构来编写脚本(条件判断或者流程控制)
#!/bin/bash
# Name:ping.sh
# Path:/test_shell/

#获取远程主机的IP地址(定义变量让用户自己输入)
read -p "请输入你要ping的远程主机ip:" ip
#使用ping命令来判断是否和远程主机互通
ping -c1 $ip &>/dev/null
if [ $? -eq 0 ];then
        echo "当前主机和远程主机$ip是互通的"
else
        echo "当前主机和远程主机$ip是不通的"
fi

或者

#!/bin/bash
# Name:ping.sh
# Path:/test_shell/

#获取远程主机的IP地址(定义变量让用户自己输入)
read -p "请输入你要ping的远程主机ip:" ip
#使用ping命令来判断是否和远程主机互通
ping -c1 $ip &>/dev/null
[ $? -eq 0 ] && echo "当前主机和远程主机$1是互通的" || echo "当前主机和远程主机$1是不通的

测试

[root@lamp test_shell]# ./ping.sh
请输入你要ping的远程主机ip:www.baidu.com
当前主机和远程主机是互通的
[root@lamp test_shell]# ./ping.sh
请输入你要ping的远程主机ip:192.168.44.25
当前主机和远程主机是不通的

2)判断一个进程是否存在

思路:
1.查看进程的相关命令ps -ef
2.根据命令的返回状态值来判断进程是否存在 $?
3.根据逻辑用脚本语言实现

#!/bin/bash
# Name:process.sh
# Path:/test_shell
# Usage:/test_shell/process.sh
# Describe:判断一个进程是否存在

#定义变量
read -p "请输入要判断的进程名:" process
#通过命令查看进程是否存在
pgrep $process &>/dev/null
#通过命令执行的状态判断是否存在
if [ $? -eq 0 ];then
        echo "进程$process存在"
else
        echo "进程$process不存在"
fi


pgrep命令:以名称为依据从运行进程队列中查找进程,并显示查找到的进程id
选项
-o:仅显示找到的最小(起始)进程号;
-n:仅显示找到的最大(结束)进程号;
-l:显示进程名称;
-P:指定父进程号;pgrep -p 4764  查看父进程下的子进程id
-g:指定进程组;
-t:指定开启进程的终端;
-u:指定进程的有效用户ID。
```shell
## 或者
[ $? -eq 0 ] && echo "进程$process存在" || echo "进程$process不存在"

测试

[root@lamp test_shell]# chmod +x process.sh
[root@lamp test_shell]# ./process.sh
请输入要判断的进程名:httpd
进程httpd存在
[root@lamp test_shell]# ./process.sh
请输入要判断的进程名:mysql
进程mysql存在

3)输入一个用户,用脚本判断该用户是否存在

#!/bin/bash
read -p "请输入需要判断的用户名:" user
id $user &>/dev/null
test $? -eq 0 && echo "$user用户存在" || echo "$user用户不存在"

测试

[root@lamp test_shell]# ./test_user.sh
请输入需要判断的用户名:test
test用户存在
[root@lamp test_shell]# ls /home
test

4)判断vsftpd软件包是否安装,如果没有则自动安装(yum源已配好)

#!/bin/bash
rpm -q vsftpd &>/dev/null
if [ $? -eq 0 ];then
        echo "vsftpd已经安装"
else
        echo "该软件没有安装,正在安装..."
        yum install -y vsftpd &> /dev/null

        if [ $? -eq 0 ];then
                echo "vsftpd安装成功"
        else
                echo "vsftpd安装失败"
        fi
fi

测试

[root@lamp test_shell]# ./auto_yum.sh
该软件没有安装,正在安装...
vsftpd安装成功

以上是关于shell选择结构(if)的主要内容,如果未能解决你的问题,请参考以下文章

shell 编程if条件判断与if 真假判断

shell脚本编程的选择分支结构

LinuxShell脚本——选择结构

Shell:结构化语句

使用if语句编写Shell脚本

shell脚本之条件语句 与 if 语句