Shell教程—流程控制之if

在我们常见的高级语言中都有if这个关键字,在shell中也有这个关键字,它也是用来做条件判断的。shell中的if的语法格式如下:

一、if语句的基本语法

1、 if

相当于C语言中的if语句

if condition ; then
   command....
   ...
fi   

最后那个fi必须要写,这也是他语法的一部分。

2、if else

相当于C语言中的if-else语句

if condtion ; then
   command...
   ....
else 
    command...
    ...
fi    
3、if else-if else
if condition1 ;then
    comand...
    ...
elif condtion2 ;then    # elif分支可以有多个
   command...
   ...
else                    # else分支只能有一个
   command
fi  

从语法上来看,shell中的if和C、Java等语言的条件判断语句还是有些许差别的,并且不光是这些差别:

  • (1)shell中的else分支如果没有语句,那就不要写出来,这样会报错
  • (2)if后的condition一定要是一个能返回true或false的语句,虽然我们常常将1认为是true、0认为是false,但是这里的condition运算结果只能是true或false,否则,即使执行结果是1或0,都会认为condition这个条件是具备的,就不走其他分支了

接下来我们就来学习一下,if的conditon该如何写。

二、Shell条件测试

Shell条件测试有两个命令test[,他们两个的作用是一样的,用于检查某个条件是否成立,可以进行数值、字符和文件三个方面的测试。[命令和test命令是两个等价的命令,他们两可以相互替换。

1、数值测试
参数说明
INTEGER1 -eq INTEGER2INTEGER1 is equal to INTEGER2 (两个数都相等为真)
INTEGER1 -ge INTEGER2INTEGER1 is greater than or equal to INTEGER2(大于等于为真)
INTEGER1 -gt INTEGER2INTEGER1 is greater than INTEGER2(大于为真)
INTEGER1 -le INTEGER2INTEGER1 is lss than or equal to INTEGER2(小于等于为真)
INTEGER1 -lt INTEGER2INTEGER1 is less than INTEGER2(小于为真)
INTEGER1 -ne INTEGER2INTEGER1 is not equal to INTEGER2(不等于为真)

示例:判断两个数大小

#!/bin/bash
#从键盘读入两个数
read -p "input 2 numbers: " num1 num2
if [ $num1 -eq $num2 ]; then  #用test命令写:if test $num1 -eq $num2; then
   echo "$num1 等于 $num2"
elif [ $num1 -gt $num2 ]; then
   echo "$num1 大于 $num2"
else 
   echo "$num1 小于 $num2" 
fi   

执行结果:

上面程序中[]可以使用test命令替换,感兴趣的小伙伴可以自行测试一下。

2、字符串测试
参数说明
-n STRING字符串的长度不为零则为真
-z STRING字符串的长度为零则为真
STRING1 = STRING2两个字符串相等
STRING1 != STRING2两个字符串不相等

示例:判断输入的两个字符串是否相等

#!/bin/bash
#输入两个字符串
read -p "input 2 strings: " str1 str2

#判断输入的字符是否有空的 字符串为空或没有定义都是0
if [ -n "$str1"  ] && [ -n "$str2" ];then
    #输入不为空
   if [ "$str1" = "$str2" ];then
      echo "$str1 equal to $str2"
    else
      echo "$str1 not equal to $str2"
    fi 
else
 #输入为空,可以要求重新输入
 echo "请不要输入空字符串"
 read -p "input 2 strings: " str1 str2
fi 
exit

执行结果:

3、文件测试
参数说明
-e FILE|DIR如果文件或目录存在则为真(常用)
-r FILE如果文件存在且当前用户可读则为真
-w FILE如果文件存在且可写则为真
-x FILE如果文件存在且可执行则为真
-s FILE如果文件存在且至少有一个字符则为真
-d DIR如果文件存在并且是目录则为真(常用)
-f FILE如果文件存在且为普通文件(常用)
-c FILE如果文件存在且为字符型特殊文件
-b FILE如果文件存在且为块特殊文件
-L FILE文件存在并且是链接文件
FILE1 -ef FILE2FILE1和FILE2具有相同的设备和inode编号
FILE1 -nt FILE2FILE1比FILE2新
FILE1 -ot FILE2FILE1比FILE2旧

示例:编写一个脚本,让用户输入一个目录的路径,脚本分别输出该目录下文件和目录的个数。

#!/bin/bash
read -p "Please input an path: " path
if [ -z "$path" ]; then
  # 没有输入路劲,不能通过
  echo "$0 :  can't resolve an empty path"
  exit
elif [ ! -d $path ]; then
  # 路径错误,不能通过
  echo "$0 : cannot access $path: No such file or directory"
  exit
else
  # 找到路径,进入统计
  dirCount=0;
  filesCount=0;
  for fileName in $(ls $path); do
      #这里应该是一个完整的路径,不然就是在判断当前路径下有没有此文件
      file=$path/$fileName
      if [ -f $file ]; then
          let filesCount++
      elif [ -d $file ] ; then
          let dirCount++
      fi
  done
  echo "$[filesCount+dirCount] files in $path.$filesCount files and $dirCount directors"   
fi   

执行结果:

4、逻辑运算符

逻辑运算符可以用于连接逻辑表达式的各个条件

参数说明举例
!逻辑非运算[ ! $fileName = "conf.d" ]
判断文件名知否叫conf.d如果是的话返回false
-a逻辑与运算,遵循逻辑短路原则[ -d $file -a `uname -s` = "Linux" ]
判断文件是否是录目录并且当前系统是Linux,如果都是,那么返回true
-o逻辑或运算,遵循逻辑短路原则[ $(uname -s) = "Linux" -o $(uname -s) = "FreeBSD" ]
判断当前系统如果是Linux或FreeBSD的话返回true
&&逻辑或,遵循逻辑短路原则a=100 b=200 [[ $a gt 50 ]] && [[ $a lt $b ]]
判断a是否大于50并且小于b,如果都满足,返回true
||逻辑与,遵循逻辑短路原则a=100 b=200 [[ $a gt 50 ]] || [[ $b lt 500 ]]
判断a是否大于50或b小于500,如果有一个满足,返回true
在Shell中if判断中多条件的写法

比如比较a>b 且 a<c,可以的写法如下:

if ((a>b)) && ((a<c))   #这是一种C系语言的写法,在Shell使用(())符号可以支持
或者
if [ $a -gt $b -a $a -lt $c ]   #这个其实使用的是shell的额test命令,只不过 [ ]符号是test的等价写法
或者
if [[ $a>$b ]] && [[$a<$c]]    #逻辑操作符方式中每个添加单独写,多个条件用逻辑运算符&&、||连接

三、if 练习

1、判断用户是否存在

执行脚本,输入一个用户名,脚本判断此用户是否存在,如果不存在时根据用户输入的Y/N来决定是否创建该用户

#!/bin/bash
set -e
read -p "Please input a username: " username

id $username &>/dev/null
if [ -n "$username" -a "$?" -eq 0 ]; then
   echo "$username already exists"
else
   read -p  "$username not exists.Do you want to create?[Y/N]: " choice
   if [ "$choice" = "Y" || "$choice" = "y" ]; then
   		useradd $username
   		if [ $? -eq 0 ]; then
   		   echo "$username create success."
   		fi
   else
      exit
    fi
fi    
2、一键检测服务器上docker是否安装、启动

首先脚本判断docker是否安装,如果没有安装就要执行安装;如果已安装,就判断docker是否启动,如果没有启动,就启动docker服务。

#!/bin/bash
#拿到docker的运行状态
docker_status=`systemctl status docker | grep "Active:" | awk '{print $2$3}'`

#检测docker是否运行
if [ -n "$docker_status" -a "$docker_status" = "active(running)" ]; then
    echo "docker is running."
else
    #检测docker是否安装
    rpm -q docker
    if [ "$?" -eq 0 ]; then
        #docker安装了,启动docker
        systemctl start docker
        #启动docker中所有容器
        containers=$(docker ps -a | awk '{print $1}' | tail -n +2)
        for container in containers; do
           docker start container $>/dev/null
           if [ "$?" -eq 0 ]; then
               echo "$container start success!" 
           else
               echo "$continer start failed!"
            fi
        done
    else
       #docker没有安装
       read -p "package Docker is not installed.Do you want to install?[Y/N]: " choice
       if [ "$choice" = "Y" -o "$choice" = "y" ]; then
           #安装gcc gcc-c++
           yum -y install gcc
           yum -y install gcc-c++
           #安装docker
           yum -y install docker
           #配置阿里云加速
           echo -e "{\"registry-mirrors\": [\"https://99o2rqoi.mirror.aliyuncs.com\"]}" >/etc/docker/daemon.json
           systemctl start docker
           systemctl enable docker  
           echo -e "\nComplete!"
       else
          echo "exit...."
       fi
    fi
fi

exit  

代码仅供参考,如有不妥之处还望大佬指出,不胜感激!!!

留言区

还能输入500个字符