Shell编程之条件判断与流程控制
编辑
892
2019-05-14
Shell编程之条件判断与流程控制
Shell流程控制语句
条件判断式
- 按照文件类型判断
- 两种判断格式
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
-
按照文件权限进行判断
操作示例
# 首先判断文件是否存在,不存在直接返回否
# 注意这里只要文件有写权限就会返回真,具体的所有者权限和所属组的权限需要进一步判断(长格式输出截取权限位来判断)
misty@ubuntu:~/MyFile/test$ [ -w ./test1.sh ] && echo "yes" || echo "no"
yes
-
两个文件之间的比较
操作实例
# 创建硬链接
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
两个整数之间的比较
Linux默认内容都是是字符类型,但是加上了数值比较的符号之后当做数字处理
操作示例
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
- 字符串的判断
注意参数比较一定要记得习惯性加上双引号,虽然一些情况下是一样的,但是,在编写一些复杂的脚本的时候需要可以规避一些问题
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
-
多重条件判断
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的语法结构和绝大多数的语言有所不同,用来帮助管理员做系统管理的
```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
操作实例-判断分区的使用率
```shell
#!/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"
- 0
- 0
-
分享