Shell流程控制语句

条件判断式

  1. 按照文件类型判断
    img
  • 两种判断格式
  • test -e /root/install.log
  • 推荐 :[-e /root/install.log]

操作示例:

misty@ubuntu:~/MyFile/test$ ls
canshu1.sh  test1.sh  test2.sh  test3.sh  test4.sh
# [] 内部两侧需要空格隔开
misty@ubuntu:~/MyFile/test$ [-e ./test1.sh]
[-e:未找到命令
misty@ubuntu:~/MyFile/test$ [ -e ./test1.sh]
bash: [: 缺少 `]'
misty@ubuntu:~/MyFile/test$ [ -e ./test1.sh ]
misty@ubuntu:~/MyFile/test$ echo $?
0
# 如果第一条命令正确执行,才会执行第二条命令。如果第二条命令正确执行,那么第三条命令不执行,否则执行第三条命令符号和上一条命令的执行情况有关
misty@ubuntu:~/MyFile/test$ [ -e ./test1.sh ] && echo "yes" || echo "no"
yes
# 第一条命令返回否,第二条命令不执行,结果传递下去,第三条命令会执行
misty@ubuntu:~/MyFile/test$ [ -e ./test1.shxxx ] && echo "yes" || echo "no"
no
# 第一条命令返回否,所以第二条命令执行,第二条命令正确执行,所以第三条命令也会执行
misty@ubuntu:~/MyFile/test$ [ -e ./test1.shxxx  ] || echo "yes" &&  echo "no"
yes
no
  1. 按照文件权限进行判断
    img

操作示例

# 首先判断文件是否存在,不存在直接返回否
# 注意这里只要文件有写权限就会返回真,具体的所有者权限和所属组的权限需要进一步判断(长格式输出截取权限位来判断)
misty@ubuntu:~/MyFile/test$ [ -w ./test1.sh  ] &&  echo "yes" ||  echo "no"
yes
  1. 两个文件之间的比较

img_shell2

操作实例

# 创建硬链接
misty@ubuntu:~/MyFile/test$ ln test1.sh tmp_test1.sh
# 查看inode值判断是否是同一个文件(inode相同)
misty@ubuntu:~/MyFile/test$ ls -lai
总用量 32
14424665 drwxr-xr-x  2 misty misty 4096 6月  29 19:16 .
31986159 drwxr-xr-x 11 misty misty 4096 6月  22 22:39 ..
14424669 -rwxr-xr-x  2 misty misty   61 6月  21 14:00 test1.sh
14424669 -rwxr-xr-x  2 misty misty   61 6月  21 14:00 tmp_test1.sh

misty@ubuntu:~/MyFile/test$ [ test1.sh -ef tmp_test1.sh ] && echo "yes" || echo "no" 
yes

  1. 两个整数之间的比较

Linux默认内容都是是字符类型,但是加上了数值比较的符号之后当做数字处理

img

操作示例

misty@ubuntu:~/MyFile/test$ [ 1 -eq 2 ] && echo "yes" || echo "no"
no
misty@ubuntu:~/MyFile/test$ [ 1 -ne 2 ] && echo "yes" || echo "no"
yes
misty@ubuntu:~/MyFile/test$ [ 1 -gt 2 ] && echo "yes" || echo "no"
no
misty@ubuntu:~/MyFile/test$ [ 1 -lt 2 ] && echo "yes" || echo "no"
yes
misty@ubuntu:~/MyFile/test$ [ 1 -ge 2 ] && echo "yes" || echo "no"
no
misty@ubuntu:~/MyFile/test$ [ 1 -le  2 ] && echo "yes" || echo "no"
yes

  1. 字符串的判断
    >注意参数比较一定要记得习惯性加上双引号,虽然一些情况下是一样的,但是,在编写一些复杂的脚本的时候需要可以规避一些问题
    img
misty@ubuntu:~/MyFile/test$ [ -z abc ] && echo "yes" || echo "no"
no
misty@ubuntu:~/MyFile/test$ [ -n abc ] && echo "yes" || echo "no"
yes
misty@ubuntu:~/MyFile/test$ [ abc ==  abc ] && echo "yes" || echo "no"
yes
misty@ubuntu:~/MyFile/test$ [ abc !=  abc ] && echo "yes" || echo "no"
no
misty@ubuntu:~/MyFile/test$ a=123
misty@ubuntu:~/MyFile/test$ b=456
misty@ubuntu:~/MyFile/test$ [ "$a" == "$b" ] &&  echo yes || echo no  
no

  1. 多重条件判断

img

misty@ubuntu:~/MyFile/test$ aa=11
# 判断aa是否有值并且大于23
misty@ubuntu:~/MyFile/test$ [ -n $aa -a $aa -gt 23 ] && echo yes || echo no
no

单分支if语句

shell的语法结构和绝大多数的语言有所不同,用来帮助管理员做系统管理的

if [ 条件判断式 ];then
    程序
fi

# 或者
if [ 条件判断式 ]
    then
    程序
fi        

单分支条件语句的注意点
* if语句使用fi结尾,和一般语言使用大括号结尾不同
* [条件判断式]就是使用test命令判断,所以中括号和条件判断式之间必须有空格
* then后面跟符号条件之后执行的程序,可以放在[]之后,用;分割,也可以写入换行符,就不需要;

操作实例-查看当前用户是否为root

#!/bin/bash
# 这里采用env而不是whoami,是为了防止用户切换获取错误
# grep行截取 ,cut列截取 -d代表分隔符 -f代表截取第几列
test=$(env |grep "USER" |cut -d "=" -f 2)

echo "$test"
if [ "$test" == root ] ;then
        echo "current user is root"

fi

操作实例-判断分区的使用率

#!/bin/bash
# 先查看指定磁盘的使用状况,再awk解析出指定列(因为是空格分割不能使用cut),再使用cut去掉%,方便数值比较
test=$( df -h |grep "/dev/disk1s1" |awk '{print $5}' |cut -d "%" -f 1 )

echo "$test"
if [ "$test" -ge 50 ] ;then
        echo "disk is flow 50%"

fi

双分支if语句

语法结构

if [ 条件判断式 ]
    then
    条件成立执行的程序
    else
    条件不成立执行的程序
fi    

操作实例:判断输入的路径时候否为目录

#!/bin/bash
# 接收用户输入一个路径
read -t 30 -p " please input a path " dir

if [ -d "$dir" ]
   then
        echo "the path is dir"
   else
        echo "the path is not dir"

fi

操作实例:判断Apache服务是否运行

#!/bin/bash
# 截取httpd进程,并把结果赋予变量test,因为grep程序也会执行,所以排除grep的截取字段
test=$(ps aux |grep "httpd" |gtep -v "grep" )


# 判断变量是否为空
if [ -n "$test" ]
        then
             echo "$(date) httpd is ok !"
        else
        # 重新启动Apache
             /etc/rd.d/init.d/httpd start &> /dev/null
             echo "$(date) restart httpd "

fi

这种方式检测,需要避免脚本命名带有关键字,脚本执行的时候,ps会出现脚本的当前进程,因为带有关键字,这种检测方式会出现误判;
更好的方式是判断端口是否被占用来判断程序是否启动

多分支条件判断

语法

if [ 条件判断式1 ]
    then
        当条件判断式1成立时执行程序1
elif [ 条件判断式2 ]
    then         
        当条件判断式2成立时执行程序2
else 
        当所有的条件都不成立时,最后执行此程序

fi         

操作实例:计算器

#!/bin/bash

read -t 30 -p "Please input num1:" num1 

read -t 30 -p "Please input num2:" num2 

read -t 30 -p "Please input operator:" ope 

# 判断输入字符是否为空
if [ -n "$num1" -a -n "$num2" -a -n "$ope" ] 

    then 

# 定义变量test1和test2 的值为   $(命令)的结果
# 后续命令的作用是,把 变量test1的值替换成空,如果能够替换成空则说明num1为数字,反之则是字符
        test1=$(echo $num1 | sed 's/[0-9]//g') 

        test2=$(echo $num2 | sed 's/[0-9]//g') 

# 判断num1和num2为数值,如果test1和test2的值为空则证明num1和num2 为数字
            if [ -z "$test1" -a -z "$test2" ] 

                then 

                    if [ "$ope" == '+' ] 

                        then 

                            result=$(($num1+$num2)) 

                    elif [ "$ope" == '-' ] 

                        then 

                            result=$(($num1-$num2)) 

                    elif [ "$ope" == '/' ] 

                        then 

                            result=$(($num1 / $num2)) 

                    elif [ "$ope" == '*' ] 

                        then 

                            result=$(($num1*num2)) 

                    else 

                        echo "Error: the input operator is worng, please input +-*/"

                        # 错误码
                        exit 111 

                    fi 

                else 

                    echo "Error: Please input numbers!"  

                    exit 222 

                fi 

        echo "$num1 $ope $num2 is $result" 

    else 

        echo "Error: You input null value!" 

        exit 333 

fi

操作实例:判断用户输入的是什么文件

#!/bin/bash
read -t 30 -p  "please input a filename:" file
# 判断文件是否为空
if [ -z "$file" ]
     then
        echo "please input content and not't input  null"
        exit 11
# 判断文件是否存在        
elif [ ! -e "$file" ]
        then
        echo "  please input file name "
        exit 12
# 判断是否为文件        
elif [ -f "$file" ]
        then
        echo  "$file is file"
# 判断是否为目录        
elif [ -d "$file" ]
      then
      echo "$file is dir "
else
     echo "$file is other file"

fi

case 语句

if ...elif ...else一样都是多分支if语句,不过和if多分支条件语句不同的是,case只判断一种条件关系,而if语句可以判断多种条件关系
case条件语法:

case $变量名 in 
    "value1")
    如果变量值为1,则执行此程序
    ;;
    “value2”
    如果变量值为1,则执行此程序
    ;;
    其他分支:***
    *)
    如果变量的值不满足以上的条件,则执行此程序
    ;;
esac    

需要注意的是,每个条件结束都要以分号结尾:

操作实例

#!/bin/bash
read -t 30 -p "please input your intention " command
#以关键字case开头
case $command in
        # condition )的方式
        "yes")
        # 这里跟上具体的业务逻辑
        echo "you input yes!"
        # 这里的;;不可以丢弃
        ;;
        "no")
        echo "you input no!"
        ;;
        # 注意这里的符号不可以加上引号
        *)
        echo "you input $command"
        ;;
# 一定要带上结尾符号esac        
esac

for循环

for循环语法

语法一:这种方式若是列举的过多代码量较多,但是符合系统管理需要,配合表达式逻辑很清晰
for 变量 in 值1 值2 值3...
    do 
        程序
    done   

语法二:
# 数值运算需要双小括号括起来
for((初始值;循环控制条件:变量变化))
    do 
    程序
    done

操作实例1:循环输出

#!/bin/bash
for i in 1 2 3 4 5 6
do
        echo $i
done

操作实例2:批量解压缩

#!/bin/bash
cd /root/test
# 过滤文件,将匹配的文件重定向到日志;
ls *.tar.gz >ls.log
ls *.tgz >>ls.log
# 循环日志中的每一个文件执行解压操作,注意表达式的写法 $(表达式)
# 当然这里若是只有一个目录和一种压缩格式的话, for i in $(ls *.tar.gz)
for i in $(cat ls.log)
        do
        #将文件输出到 /dev/null,相当于信息不会显示也不会保存
                tar -zxvf $i > /dev/null
        done
# 解压完成删除文件记录
rm -rf ls.log

操作实例3:从1加到100

#!/bin/bash
#从1加到100
s=0
# 注意算数运算需要双引号括起来
for((i=1;i<=100;i=i+1))
do
        # s=(($s+$i))也可以
        s=$(($s+"$i"))
done
echo "the sum of (1+2+...100) is $s"

操作实例4:批量添加用户

#!/bin/bash
# 批量添加指定数量的用户
read -p "Please input user name :"-t 30 name 
read -p "Please input the number of user :"-t 30 num 
read -p "Please input user password of user  :"-t 30 pass 
# 判断参数是否非空,其实 -n 更好不用取反
if [ ! -z "$name"  -a ! -z "$num" -a  ! -z "$pass"]
    then 
        y=$(echo $num | sed 's/[0-9]//g')
        # 判断输入是否为数字,如果数字替换了为空则为数字
        if [ -z "$y"]
        then 
        for ((i=1;i<$num;i=i+1))
            do 
                /user/sbin/useradd $name$i &>dev/null

                # 批量删除用户,只需要这一句话即可,-r连带家目录一起删除 /user/sbin/userdel -r $name$i &>dev/null

                # 使用echo的返回值作为创建的用户的密码
                echo $pass | /user/bin/passwd --stdin $name$i &>/dev/null
            done
        fi    
fi       
# 查看用户
cat /etc/passwd

操作实例4:批量删除普通用户

#!/bin/bash
# 首先普通用户是可以登陆的包含有/bin/bash,匿名用户不可以登陆包含/sbin/nologin
# 另外不能删除root,所以需要对排除root ,再以:分割,截取第一列的数据
users=cat /etc/passwd |grep /bin/bash |grep -v root |cut -d ":" -f 1
for i in $user
    do 
        # 删除用户以及其家目录的数据 
        userdel -r $i
    done

while循环和until循环

while循环:不定循环,也称作条件循环,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立
循环才会停止
操作实例:从1加到100 while实现

#!/bin/bash
# 从1加到100
i=1
s=0
# 当i<=100 则进行循环 
while [ $i -le 100 ]
do 
    s=$(($s+$i))
    i=$(($i+1))
done
echo "the sum is : $s"

until 循环,和while循环相反,util循环时只要条件判断式不成立则进行循环,并执行循环程序,一旦循环条件成立
则终止循环

操作实例:从1 加到100 until实现

#!/bin/bash
# 从1加到100
i=1
s=0
# 直到i>100则终止循环
until [ $i -gt 100 ]
do 
    s=$(($s+$i))
    i=$(($i+1))

done
echo "the sum is : $s"