前言:

在linux shell中,通常我们将一些命令写在一个文件中就算是一个shell脚本了,但是如果需要执行更为复杂的逻辑判断,我们就需要使用流程控制语句来支持了。

所谓流程控制既是通过使用流程控制语句对程序流程的选择、循环、转向和返回等进行控制。流程控制是所有编程语言分重要组成部分,linux shell同样有一套自己的流程控制语句,其中主要包括条件语句(if),循环语句(for,while),选择语句(case)。本文将会对这几种语句进行介绍同时引用示例便于大家理解。文章也会涉及到循环控制语句的介绍,以及while循环的一些常用的特殊用法,快来一起学习吧!

一、条件选择if语句

单分支

if 判断条件;then
条件为真的分支代码
fi

双分支

if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi

多分支

if 判断条件1; then
条件为真的分支代码
elif 判断条件2; then
条件为真的分支代码
elif 判断条件3; then
条件为真的分支代码
else
以上条件都为假的分支代码
fi

逐条件进行判断,第一次遇为“真”条件时,执行其分支, 而后结束整个if语句

二、条件判断case语句:

case 变量引用 in 		#变量的引用加$
PAT1)
分支1
;;
PAT2)
分支2
;;
...
\*)
默认分支
;;
esac

case支持glob风格的通配符:

*: 任意长度任意字符

?: 任意单个字符

[]:指定范围内的任意单个字符

a|b: a或b

练习:编写脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息

[root@CentOS6 bin]#vim iduser.sh
1 #!/bin/bash
2 #---------------+--------------------------------------+
3 # ☆ Author : huxiaoqi
4 # ☆ Email : 345304057@qq.com
5 # ☆ Blog : http://www.cnblogs.com/qige2017/
6 # ☆ Tel : 13598859921
7 # ☆ Create time : 2017-08-28
8 # ☆ Filename : iduser.sh
9 # ☆ Version : 1.2.1
10 #---------------+--------------------------------------+
11 read -p "Please input the user name: " username #交互式输入用户名,复制给username
12 if id $username &>/dev/null ;then #条件判断用户输入的用户名是否存在
13 echo "$username is exist" #用户名已存在满足条件,打印exist
14 else
15 echo "user$username is cresting.."
16 sleep 1
17 useradd $username &> /dev/null #用户名不存在就创建用户
18 finger $username #查看用户相关信息
19 fi

三、for循环:

for 变量名 in 列表;do
循环体
done
[root@CentOS7 ~]#for id in {10..1..2};do echo The number is $id ;done
The number is 10 #列表也可以`seq 2 2 10`
The number is 8 #同样表示2到10步进2
The number is 6 #因为是命令所以用反引号引起来
The number is 4
The number is 2

执行机制:

依次将列表中的元素赋值给“变量名”; 每次赋值后即执 行一次循环体; 直到列表中的元素耗尽,循环结束

列表生成方式:

  1. 直接给出列表
  2. 整数列表:

    (a) {start..end}

    (b) $(seq [start [step]] end)
  3. 返回列表的命令

    $(COMMAND)
  4. 使用glob,如:*.sh
  5. 变量引用; $@, $*

练习:用for实现

1、添加10个用户user1-user10,密码为8位随机字符

[root@CentOS6 bin]#vim useradd10.sh
#!/bin/bash
> /root/user.log #创建并每次清空密码记录文件
for i in {1..10};do #1-10 循环10次
if id user$i &> /dev/null ;then #判断用户是否存在
echo user$i is exist
exit 1 #若存在则退出脚本,有漏洞可以用后边的知识跳过本次循环
fi
useradd user$i &> /dev/null && echo user$i is created
passwd=`cat /dev/urandom | tr -dc 'a-cA-Z0-9' |head -c 8`
#取/dev/urandom文件中的随机字符,tr -dc 'a-cA-Z0-9' |head -c 8 过滤删 除除了大小写字母以及数字的字符,并取前八个(cat /dev/urandom每次生成的随机 数都不一样)。并且赋值passwd变量。
echo $passwd | passwd --stdin user$i &> /dev/dull
passwd -e user$i &> /dev/null
#将用户的密码修改为$passwd,并设置强制登录修改密码
echo user$i:$passwd >> /root/user.log
#将用户名和对应的用户密码重定向到/root/user.log中
done [root@CentOS6 ~]#cat user.log
user1:THUU66I0
批量创建用户
[root@CentOS6 ~]#echo user{1..10} |xargs -n1 useradd
批量删除用户
[root@CentOS6 ~]#echo user{1..10} |xargs -n1 userdel -r

2、计算100以内所有能被3整除的整数之和

步进思路:
[root@CentOS6 bin]#vim be3.sh
#!/bin/bash
sum=0 #进入循环之前总合为0
for i in `seq 3 3 100`;do #以3开始步进3到100,既取出所有3-100被三整除的数
sum=$[i+sum] #进入循环以后,sum自增方括号内是数值运算不用加空格
其他写法:let sum+=i 或者sum=$((i+$sum)) 小括号方括号内均为数值运算$可以省略
done
echo $sum
取模思路:
sum1=0
for ii in `seq 1 100`;do
if [ $((ii%3)) -eq 0 ];then #若返回值为0则继续执行任务
#计算机只支持整数运算,若ii的值不能被3整除则返回值为假,既不等于0
sum1=$[ii+sum1]
fi
done
echo sum1 is: $sum1
tr思路:
echo {3..100..3}|tr ' ' +|bc
seq思路:
seq -s + 3 3 100 |bc #-s:指定分隔符为+号

3、打印九九乘法表

for l in `seq 9`;do			#l:行数循环9次
for q in `seq $l`;do #q列数嵌套循环,每行的列数=当前行数
p=$[q*l] #p为乘积
echo -n "$q*$l=$p " #内层循环,也就是每一行内的循环echo不换行
done
echo #外层循环要换行
done
[root@CentOS6 bin]#99.sh
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81

4、打印等腰三角形

[root@CentOS6 bin]#vim triangle.sh
#!/bin/bash
read -p "please input the storey of the triangle: " n
for l in `seq $n` ; do #命令的引用可以用反引号或者$()
for s in `seq $((n-l))`; do #空格数=总行数减当前行数,bash中的算术运算:var=$((算术表达式))或者 var=$[算术表达式]
echo -n " "
done
for t in `seq $((2*l-1))`;do #星数=当前行数*2-1
echo -n "*"
done
echo #每次最外层循环后换行
done
[root@CentOS6 bin]#triangle.sh
please input the storey of the triangle: 5
*
***
*****
*******
*********

四、while循环

用法展示:

while CONDITION; do
循环体
done

CONDITION:循环控制条件;进入循环之前,先做一次判 断;每一次循环之后会再次做判断;条件为“true”,则执行 一次循环;直到条件测试状态为“false”终止循环 。

因此:CONDTION一般应该有循环控制变量;而此变量的值 会在循环体不断地被修正。

进入条件:CONDITION为true

退出条件:CONDITION为false

练习:用while循环实现

1、编写脚本,提示请输入网络地址,如192.168.0.0,判断 输入的网段中主机在线状态,并统计在线和离线主机各多少

[root@CentOS6 bin]#vim whileip.sh
#!/bin/bash
read -p "please input the ip(eg:172.18.0.1): " ip
network=`echo $ip |cut -d "." -f1-3` #C类地址前三位为网络id
i=1 #ip一般从1开始
up=0
down=0
while [ $i -le 254 ];do #255作为网段内的广播ip,所以取1-254之内的循环
if ping -c1 -w1 $network.$i > /dev/null;then #ping一次一秒
echo $network.$i is up!
let up++ #统计开机主机数
else
echo $network.$i is down!
let down++ #统计关机主机数
fi
let i++
done

2、编写脚本,实现打印国际象棋棋盘

思路:

  1. 棋盘分八行八列,外层循环八次表示行数,内层循环八次表示列数
  2. 打印空格加底色实现棋盘效果
  3. 总结规律发现当当前行数与当前列数相加为偶数时打印黄色,当当前行数与当前列数相加为奇数时打印红色
[root@CentOS6 bin]#vim chess.sh
#!/bin/bash
i=1 #初始行数为1进入循环
while [ $i -le 8 ];do #行数小于等于8则继续任务
j=1 #初始列数为1进入内层循环
while [ $j -le 8 ];do #列数小于等于8册继续任务
flag=$[$[i+j]%2] #标记当前行数当前列数和的奇偶性
if [ $flag -eq 0 ];then #当$flag为偶数打印黄色
echo -n -e "\033[43m \033[0m"
else #当$flag为奇数数打印红色
echo -n -e "\033[41m \033[0m"
fi
let j++ #列数自增
done
let i++ #行数自增
echo
done

while的无限循环写法

冒号:

ture

两个反引号``

作为while的循环控制条件,返回值永远为真,可以无限循环。

[root@CentOS7 ~]#while true ; do echo hello ; sleep 1 ; done
hello
hello

let 自增赋值坑

之前学习bash算法时有关于自增赋值先后区别的描述,这一区别在while循环用法中得以体现:

[root@CentOS6 bin]#i=0;let i=++i;echo $?
0 #当初始值为0时使用let i=++i 先自增再赋值返回值为真
[root@CentOS6 bin]#i=0;let i=i++;echo $?
1 #当初始值为0时使用let i=++i 先赋值再自增返回值为假

五、until循环

用法展示:

until CONDITION; do
循环体
done

原理与while相反:

进入条件: CONDITION 为false

退出条件: CONDITION 为true

练习until:

每隔3秒钟到系统上获取已经登录的用户的信息;如果发 现用户tianbaobao登录,则将登录时间和主机记录于日志 /app/login.log中,并退出脚本

[root@CentOS6 bin]#vim untilwho.sh
#!/bin/bash
until who | grep "^tianbaobao\>" &>> /app/login.log ; do
#用grep过滤who命令以tianbaobao开头的输出结果作为until的条件判断
sleep 3 #每隔三秒
done

六、循环控制语句continue

在循环任务中,如果遇到continue就跳过本次循环,执行下一次循环

continue后边加参数continue [N]:指定提前结束第N层的本轮循环,而直接进入下一 轮判断;最内层为第1层

while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue #如果满足条件2执行continue
fi
CMDn #跳过接下来的任务,但是继续执行循环任务
...
done

七、循环控制语句break

在循环任务中,如果遇到break就结束整个循环任务。

break后边加参数break [N]:指定提前结束第N层循环,最内层为第1层

while CONDTIITON1; do
CMD1
...
if CONDITION2; then
break ##如果满足条件2,执行break直接结束整个循环任务
fi
CMDn
...
done

八、循环控制shift命令

shift [n]

用于将参量列表 list 左移指定次数,默认为左移一次。

参量列表 list 一旦被移动,最左端的那个参数就从列表中删 除。

while 循环遍历位置参量列表时,常用到 shift

示例:

while [ $# -gt 0 ] # or (( $# > 0 ))
do
echo $*
shift
done

练习shift:

利用shift实现批量创建用户

[root@CentOS6 bin]#vim useraddshift.sh
#!/bin/bash
while [ $# -gt 0 ] ;do #如果参数大于零进入循环
id $1 &> /dev/null && continue #如果用户已存在就跳过本次循环
useradd $1 && echo $1 is created
shift #移除$1,$2左移成为下次循环的$2
done

九、特殊用法

while循环的特殊用法(遍历文件的每一行):

while read line; do
循环体
done < /PATH/FROM/SOMEFILE

依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将 行赋值给变量line

双小括号写法

双小括号方法,即((…))格式,也可以用于算术运算

双小括号方法也可以使bash Shell实现C语言风格的变量操作

I=10

((I++))

for循环的特殊格式:

for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done

控制变量初始化:仅在运行到循环代码段时执行一次

控制变量的修正表达式:每轮循环结束会先进行控制变量修 正运算,而后再做条件判断

练习特殊用法:

计算1-100所有数字之和

[root@CentOS6 bin]#vim 1-100sum.sh
1 #!/bin/bash
2 #---------------+--------------------------------------+
3 # ☆ Author : huxiaoqi
4 # ☆ Email : 345304057@qq.com
5 # ☆ Blog : http://www.cnblogs.com/qige2017/
6 # ☆ Tel : 13598859921
7 # ☆ Create time : 2017-08-26
8 # ☆ Filename : 1-100sum.sh
9 # ☆ Version : 1.2.1
10 #---------------+--------------------------------------+
11 i=1 #初始化
12 sum=0
13 while [ $i -le 100 ];do #i小于等于100既进入循环
14 let sum+=i #求和
15 let i++ #i自增
16 done
17 echo usm is: $sum
18 i=1 sum=0
19 while [ $i -le 100 ];do
20 sum=$[i+sum]
21 let i++
22 done
23 echo sum1 is: $sum
24 for ((sum=0,i=0;i<=100;i++))#利用双小括号写法
#sum,i=0控制变量初始化;i<=100条件判断表达式;i++控制变量修正表达式
25 do
26 let sum+=i
27 done
28 echo sum2 is: $sum
29 i=1
30 sum=0
31 while ((i<=100))
32 do
33 let sum+=i
34 let i++
35 done
36 echo sum3 is: $sum
37 unset i sum
四种方法
[root@CentOS6 bin]#1-100sum.sh
usm is: 5050
sum1 is: 5050
sum2 is: 5050
sum3 is: 5050

这个脚本写法比较正规,题头比较完整,变量的初始化以及sunset都有,逻辑清晰有条理,排版合理大家可以参照养成良好的编写脚本的习惯。

十、select循环与菜单

select variable in list 	#variable:变量名
do
循环体命令
done

select 循环主要用于创建菜单,按数字顺序排列的 菜单项将显示在标准错误上,并显示 PS3 提示符, 等待用户输入

(PS1:命令行提示符;PS2:多行重定向提示符)

用户输入菜单列表中的某个数字,执行相应的命令

用户输入被保存在内置变量REPLY中

select 是个无限循环,因此要记住用 break 命令退 出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环

select 经常和 case 联合使用

与 for 循环类似,可以省略 in list,此时使用位置参量

练习select:

制作菜单,要求顾客输入对应食物的编号就显示价格

[root@CentOS6 bin]#vim selectmenu.sh
PS3="Please choose your food: "
select menu in lamian huimian hulatang yangroutang ;do
case $REPLY in
1)
echo "The price is \$10"
;;
2)
echo "The price is \$15"
;;
3)
echo "The price is \$5"
;;
4)
echo "The price is \$20"
;;
*)
echo "No such food"
break #select语句是一个死循环与break配合使用
;;
esac
done
[root@CentOS6 bin]#selectmenu.sh
1) lamian #selsct语句自动列出菜单,并且定义用户需要输入的编号
2) huimian #将用户输入的编号赋值给REPLY
3) hulatang
4) yangroutang
Please choose your food: 1
The price is $10
Please choose your food: 2
The price is $15
Please choose your food: 5
No such food

关于linux shell流程控制的知识就介绍到这儿啦,怎么样,看完是不是觉得文章真的是又简单易懂又实用呢?希望以上的内容能给你带来帮助,有疑问以及要指正的错误,请留言吧!

shell编程流程控制的更多相关文章

  1. 10、shell编程+流程控制+分支嵌套

    SHELL 编程     shell 是一个命令解释器,侦听用户指令.启动这些指令.将结果返回给用户(交互式的shell)     shell 也是一种简单的程序设计语言.利用它可以编写一些系统脚本. ...

  2. shell编程--流程控制for,do-while,if-then,break,continue,case等

    2.5 流程控制 2.5.1 if语法 1.语法格式 if condition then     statements [elif condition     then statements. ..] ...

  3. Linux学习 -- Shell编程 -- 流程控制

    if语句 单分支 if [ 条件判断式 ]; then 程序 fi 或者 if [ 条件判断式 ] then 程序 fi 例子: 双分支 if [ 条件判断式 ] then 程序 else 程序 fi ...

  4. linux shell编程流程控制

    条件选择 单分支条件 多分支条件 选择执行if语句 单分支 if 判断条件;then 条件为真的分支代码 fi 双分支 if 判断条件; then 条件为真的分支代码 else 条件为假的分支代码 f ...

  5. Shell工具| 流程控制

    1. 流程控制 if 判断 ()[ 条件判断式 ],中括号和条件判断式之间必须有空格 ()if后要有空格 [kris@hadoop datas]$ vim if.sh #!/bin/bash -eq ...

  6. linux shell 之流程控制 if if else while

    (1)流程控制不可以为空: (2)if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi 条件 ...

  7. shell 10流程控制

    if 判断 if #shell #!/bin/sh a=5 if [[ $a > 3 ]];then echo "$a>3" fi #写成一行 if [[ $a < ...

  8. shell之流程控制

    一.if语句.while.for循环各种小例题 1.用户验证 [root@bogon ~]# cat buer.sh #!/bin/bash #user='buer' #password='1234. ...

  9. shell编程3 ---流程控制语句

    shell编程流程控制语句 一.if流程控制语句 1.单分支if条件判断语句 if [  条件判断式 ]:then     或者   if[ 条件判断式 ] 程序                   ...

随机推荐

  1. Machine Learning:Neural Network---Representation

    Machine Learning:Neural Network---Representation 1.Non-Linear Classification 假设还採取简单的线性分类手段.那么会面临着过拟 ...

  2. nanoporetech/nanonet

    nanoporetech/nanonet CodeIssues 7Pull requests 0Projects 0Wiki Insights  First generation RNN baseca ...

  3. 线程中调用Updatedata的问题

    随便发个自定义消息,然后在 CMyDialog的自定义消息处理函数中 UpdateDate().因为 UpdateDate用到了线程本地存储.不能跨线程的 UpdateData只能在主线程中使用,将U ...

  4. iOS8 PUSH解决方法

    本文转载至 http://blog.csdn.net/pjk1129/article/details/39548523     - (void)registerForRemoteNotificatio ...

  5. wince c# 创建桌面快捷方式 .

    static void Create() { string PathGPRS = System.IO.Path.GetDirectoryName(System.Reflection.Assembly. ...

  6. RTSPClient工具EasyRTSPClient支持H.265,支持海思等各种芯片平台

    EasyRTSPClient是EasyDarwin开源流媒体团队开发.提供的一套非常稳定.易用.支持重连的RTSPClient工具,接口调用非常简单,再也不用像调用live555那样处理整个RTSP ...

  7. 九度OJ 1108:堆栈的使用 (堆栈)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6705 解决:1974 题目描述: 堆栈是一种基本的数据结构.堆栈具有两种基本操作方式,push 和 pop.Push一个值会将其压入栈顶, ...

  8. (t,p,o) t:p>=o there cannot be more consumer instances in a consumer group than partitions

    https://kafka.apache.org/intro.html Kafka as a Messaging System How does Kafka's notion of streams c ...

  9. 在DuiLib中使用MFC类

    比如,想在DuiLib里使用MFC中的CInternetSession 首先,将Project Properties->General->Use of MFC设置为Use MFC in a ...

  10. Raspberry Pi3 ~ 安装 nfs Server

    l  安装必要服务: sudo      apt-get install  portmap sudo  apt-get install  nfs-kernel-server sudo      apt ...