跳到主要内容

shell流程控制

if判断语句

格式

if [ condition ]
then
commands
fi

if...else

if [ condition ]     
then
commands1
else
commands2
fi

if...elif...else

if [ condition 1 ]
then
command1
elif [ condition 2 ]
then
commands2
.......
else
commandsX
fi

比较运算、逻辑运算、文件运算皆可用于if条件。

if的高级特性

双圆括号

if (( expression-condition ))

可以在条件中植入数学表达式

if (( (5+5-5)*5/5 > 10 ))
then
echo "yes"
else
echo "no"
fi

双方括号

可以在条件中使用通配符。

for var in  ab ac rx bx rvv vt
do
if [[ "$var" == r* ]]
then
echo "$var"
fi
done

简写if

条件为真采用&&符号链接命令块,条件为假采用||链接命令块。

if [ ! -d /tmp/baism ]
then
mkdir /tmp/baism
fi

可以简写为

[ ! -d /tmp/baism ] && mkdir /tmp/baism
if [ $USER == 'root' ]
then
echo "hello root"
else
echo "hello guest"
fi

可以简写
[ $USER == 'root' ]&&echo "hello root" || echo "hello guest"

for循环语句

基本格式

for variable_name in {list}
do
command
command

done

or

for variable in a b c
do
command
command
done

for条件的赋值方式

范围

for var in {1..10}
do
echo $var
done

命令

for var in `seq  10`
do
echo $var
done

直接赋值

for var in 1 2 3 4 5
do
echo $var
done

其他花式赋值

[21:45:30 root@VM-8-17-centos ~]#for var in $(seq 5);do echo $var;done
1
2
3
4
5
[21:45:40 root@VM-8-17-centos ~]#for var in {5..1};do echo $var;done
5
4
3
2
1
[21:46:06 root@VM-8-17-centos ~]#for var in {0..10..2};do echo $var;done
0
2
4
6
8
10
[21:46:36 root@VM-8-17-centos ~]#for var in {10..1..-2};do echo $var;done
10
8
6
4
2
[21:47:19 root@VM-8-17-centos ~]#for var in `seq 10 -2 1`;do echo $var;done
10
8
6
4
2

还能从shell的参数获取

#!/bin/bash
#
for i in $@;do
echo $i
sum=$((sum+$i))
done
echo "平均数为"$[$sum/$#]
echo "总和为"$sum
[22:28:18 root@study]#bash sum.sh 22 55 74
22
55
74
平均数为50
总和为151

不带列表的循环

不带列表的for循环执行时由用户指定参数和参数的个数

#!/bin/bash
# nonelist-for.sh
for var
do
echo $var
done

echo "脚本后面有$#个参数"

执行以上脚本

[22:13:07 root@study]#bash nonelist-for.sh A
A
脚本后面有1个参数
[22:13:19 root@study]#bash nonelist-for.sh A 3 33
A
3
33
脚本后面有3个参数

for嵌套

嵌套for

#!/bin/bash
#
#Author:
#Created Time:
#Release:
#Description: 打印99乘法表
for ((A=1;A<=9;A++))
do
for ((B=1;B<=$A;B++))
do
echo -n -e "$B*$A=$((A*B)) \t"
done
#换行
echo
done

嵌套if

#!/bin/bash
#Description:输出1-9,当输出5时停止输出

for ((num=1;num<10;num++))
do
echo $num
[ $num -eq 5 ]&& break
done

for循环与数组

使用for循环遍历读出数组

name=('tom' 'jarry' 'harry' 'barry')
for i in 0 1 2 3
do
echo ${name[$i]}
done

使用for循环进行数组存值

for i in `seq 0 9`
do
read -p "name: " name[$i]
done

while循环语句

应用在未知循环次数的环境。条件为真就进入循环;条件为假就退出循环。

语法:

while [ 表达式 ]
do
command...
done

while [ 1 -eq 1 ] 或者 (( 1 > 2 ))
do
command
command
...
done

特殊条件

while语句中可以使用特殊条件来进行循环:

  • 符号":" 条件代表真,适用与无限循环
  • 字符串 “true” 条件代表真,适用与无限循环
  • 字符串 "false"条件代表假

while嵌套

while可以嵌套if、for、while

#!/bin/bash
#Description: 99乘法表
A=1
while [ $A -lt 10 ]
do
#定义B
B=1
while [ $B -le $A ]
do
echo -n -e "$B*$A=$((A*B)) \t"
let B++
done

echo
let A++
done

循环控制

sleep语句

作用:控制循环几秒一次

#!/bin/bash 
#Description: 倒计时游戏

#1.定义初始值
time=9

#2.循环输出,1秒一次
while [ $time -ge 0 ]
do
echo -n -e "\b$time"
let time--
#控制循环 1秒一次
sleep 1
done

break语句

作用: 终止循环,执行循环体后面的代码

#!/bin/bash
#Description: 输出数字1-9,当输出5时停止
num=1
while [ $num -lt 10 ]
do
echo $num

#判断当前num的值,如果等于5就跳出循环
if [ $num -eq 5 ]
then
break
fi
let num++
done

continue语句

作用: 跳过某次循环,继续执行下一次循环;表示循环体内下面的代码不执行,重新开始下一次循环

#!/bin/bash
#Description: 输出数字1-9,当等于5时跳过本次循环,输出1、2、3、4、6、7、8、9
num=0
while [ $num -lt 9 ]
do
let num++
#判断当前num的值,如果等于5就跳过本次循环
if [ $num -eq 5 ]
then
continue
fi
echo $num
done

参数控制命令shift

作用: 外部传参到循环时,参数管理命令

使位置参数向左移动,默认移动1位,可以使用shift n。传参个数要是n的整数倍,否则最后会一直剩下一个参数

#!/bin/bash

[ $# -lt 3 ]&&echo '请输入至少三个参数:'$0' $1 $2 $3 ...'&&exit 1
count=$#

#通过shift左移参数输出
#使位置参数向左移动,默认移动1位,可以使用shift 2,传参要是2的整数倍
for ((i=1;i<=$count;i++))
do
echo '目前参数数量: '$#''
echo '当前$1的数值是: '$1''
shift 1
sleep 1
done
echo "执行完毕"
[root@study]#bash shift.sh 3 5 7 2 
目前参数数量: 4
当前$1的数值是: 3
目前参数数量: 3
当前$1的数值是: 5
目前参数数量: 2
当前$1的数值是: 7
目前参数数量: 1
当前$1的数值是: 2
执行完毕

脚本退出命令exit

作用: 退出程序并释放占用的系统资源

for i in `seq 1 9`
do
echo $i
if [ $i -eq 5 ]
then
exit 0 # 退出脚本,返回状态码0
fi
done
echo "执行完毕"

流程控制 until语句

一个类似while的循环语句,不同于while的是,当条件为假时开始until循环。

条件为假就进入循环;条件为真就退出循环。

until expression
do
command
command
...
done

i=1
while [ $i -le 5 ]
do
echo $i
let i++
until [ $i -le 5 ]
do
echo $i
let i++
[ $i -eq 10 ]&&break
done
done

case语句

特点:根据给予的不同条件执行不同的代码块

语法:

case $var in            # 定义变量;var代表是变量名
pattern 1)
command1 # 需要执行的语句
;; # 两个分号代表命令结束
pattern 2)
command2
;;
pattern 3)
command3
;;
*) # default,不满足以上模式,默认执行*)下面的语句
command4
;;
esac # esac表示case语句结束

例:nginx启动管理脚本 nginx.sh

bash nginx.sh start|stop|restart|reload|status

#!/bin/bash
#Description:
#Author: www.zutuanxue.com
#Created Time:
#nginx service manage script

#variables
nginx_install_doc=/usr/local/nginx
proc=nginx
nginxd=$nginx_install_doc/sbin/nginx
pid_file=$nginx_install_doc/logs/nginx.pid

# Source function library.
if [ -f /etc/init.d/functions ];then
. /etc/init.d/functions
else
echo "not found file /etc/init.d/functions"
exit
fi

#假如pid文件存在,那么统计一下nginx进程数量
if [ -f $pid_file ];then
nginx_process_id=`cat $pid_file`
nginx_process_num=`ps aux |grep $nginx_process_id|grep -v "grep"|wc -l`
fi


#function
start () {
#如果nginx 没有启动直接启动,否则报错 已经启动
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
echo "nginx running..."
else
#如果pid文件存在,但是没有进程,说明上一次非法关闭了nginx,造成pid文件没有自动删除,所以启动nginx之前先删除旧的pid文件
if [ -f $pid_file ] && [ $nginx_process_num -lt 1 ];then
rm -f $pig_file
#可以使用两个函数,两种方法来执行命令,并返回执行结果
#1)daemon
#2)action 建议这个,简单易用

#echo " nginx start `daemon $nginxd` "
action "nginx start" $nginxd
fi
#echo " nginx start `daemon $nginxd` "
action "nginx start" $nginxd
fi

}

stop () {
#判断nginx启动的情况下才会执行关闭,如果没启动直接报错,或者提示用户服务没启动,这里我直接报错的原因是为了给大家演示失败的输出
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
action "nginx stop" killall -s QUIT $proc
rm -f $pid_file
else
action "nginx stop" killall -s QUIT $proc 2>/dev/null
fi
}

restart () {
stop
sleep 1
start
}

reload () {
#重载的目的是让主进程重新加载配置文件,但是前提是服务必须开启
#这里先判断服务是否开启,开启就执行加载,没有开启直接报加载错误
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
action "nginx reload" killall -s HUP $proc
else
action "nginx reload" killall -s HUP $proc 2>/dev/null
fi
}

status () {
if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then
echo "nginx running..."
else
echo "nginx stop"
fi
}

#callable
case $1 in
start) start;;
stop) stop;;
restart) restart;;
reload) reload;;
status) status;;
*) echo "USAGE: $0 start|stop|restart|reload|status";;

esac