流程控制是改变程序运行顺序的指令。

4.1 if语句

4.1.1 单分支

if 条件表达式; then
命令
fi

示例:

#!/bin/bash
N=10
if [ $N -gt 5 ]; then
echo yes
fi
# bash test.sh
yes

4.1.2 双分支

if 条件表达式; then
命令
else
命令
fi

示例1:

#!/bin/bash
N=10
if [ $N -lt 5 ]; then
echo yes
else
echo no
fi
# bash test.sh
no

示例2:判断crond进程是否运行

#!/bin/bash
NAME=crond
NUM=$(ps -ef |grep $NAME |grep -vc grep)
if [ $NUM -eq 1 ]; then
echo "$NAME running."
else
echo "$NAME is not running!"
fi

示例3:检查主机是否存活

#!/bin/bash
if ping -c 1 192.168.1.1 >/dev/null;then
echo "OK."
else
echo "NO!"
fi

if语句可以直接对命令状态进行判断,就省去了获取$?这一步!

4.1.3 多分支

if 条件表达式; then
命令
elif 条件表达式; then
命令
else
命令
fi

当不确定条件符合哪一个时,就可以把已知条件判断写出来,做相应的处理。

示例1:

#!/bin/bash
N=$1
if [ $N -eq 3 ]; then
echo "eq 3"
elif [ $N -eq 5 ]; then
echo "eq 5"
elif [ $N -eq 8 ]; then
echo "eq 8"
else
echo "no"
fi

如果第一个条件符合就不再向下匹配。

示例2:根据Linux不同发行版使用不同的命令安装软件

#!/bin/bash
if [ -e /etc/redhat-release ]; then
yum install wget -y
elif [ $(cat /etc/issue |cut -d' ' -f1`) =="Ubuntu" ]; then
apt-get install wget -y
else
Operating system does not support.
exit
fi

4.2 for语句

for 变量名 in 取值列表; do
命令
done

示例:

#!/bin/bash
for i in {1..3}; do
echo $i
done
# bash test.sh
1
2
3

for的语法也可以这么写:

#!/bin/bash
for i in $@; {
echo $i
}
# bash test.sh 1 2 3
1
2
3

默认for循环的取值列表是以空白符分隔,也就是第一章讲系统变量里的$IFS:

#!/bin/bash
for i in 12 34; do
echo $i
done
# bash test.sh
12
34

如果想指定分隔符,可以重新赋值$FS变量:

#!/bin/bash
OLD_IFS=$IFS
IFS=":"
for i in $(head -1 /etc/passwd); do
echo $i
done
IFS=$OLD_IFS # 恢复默认值
# bash test.sh
root
x
0
0
root
/root
/bin/bash

for循环还有一种C语言风格的语法:

#!/bin/bash
for ((i=1;i<=5;i++)); do
echo $i
done

示例1:检查多个主机是否存活

#!/bin/bash
for ip in 192.168.1.{1..254}; do
if ping -c 1 $ip >/dev/null; then
echo "$ip OK."
else
echo "$ip NO!"
fi
done

示例2:检查多个域名是否可以访问

#!/bin/bash
URL="www.baidu.com www.sina.comwww.jd.com"
for url in $URL; do
HTTP_CODE=$(curl -o /dev/null -s -w %{http_code} http://$url)
if [ $HTTP_CODE -eq 200 -o $HTTP_CODE -eq 301 ]; then
echo "$url OK."
else
echo "$url NO!"
fi
done

4.3 while语句

while 条件表达式; do
命令
done

示例1:

#!/bin/bash
N=0
while [ $N -lt 5 ]; do
let N++
echo $N
done
# bash test.sh
1
2
3
4
5

当条件表达式为true时,终止循环。

示例2:条件表达式为true,将会产生死循环

#!/bin/bash
while [ 1 -eq 1 ]; do
echo "yes"
done

也可以条件表达式直接用true:

#!/bin/bash
while true; do
echo "yes"
done

还可以条件表达式用冒号,冒号在Shell中的意思是不做任何操作。但状态是0,因此为true:

#!/bin/bash
while :; do
echo "yes"
done

示例3:在死循环中,满足条件终止循环

#!/bin/bash
N=0
while true; do
let N++
if [ $N -eq 5 ]; then
break
fi
echo $N
done
# bash test.sh
1
2
3
4

里面用了if判断,并用了break语句,它是跳出循环。与其关联的还有一个continue语句,它是跳出本次循环。

示例4:举例子说明continue用法

#!/bin/bash
N=0
while [ $N -lt 5 ]; do
let N++
if [ $N -eq 3 ]; then
continue
fi
echo $N
done
# bash test.sh
1
2
4
5

当变量N等于3时,continue跳过了当前循环,没有执行下面的echo。

注意:continue与break语句只能循环语句中使用。

示例5:逐行处理文本

文本内容:

# cat a.txt
a b c
1 2 3
x y z

要想使用while循环逐行读取a.txt文件,有三种方式:

方式1:
#!/bin/bash
cat ./a.txt | while read LINE; do
echo $LINE
done
方式2:
#!/bin/bash
while read LINE; do
echo $LINE
done < ./a.txt
方式3:
#!/bin/bash
exec < ./a.txt # 读取文件作为标准输出
while read LINE; do
echo $LINE
done

与while关联的还有一个until语句,它与while不同之处在于,是当条件表达式为false时才循环,实际使用中比较少,这里不再讲解。

4.4 case语句

case语句一般用于选择性来执行对应部分块命令。

case 模式名 in
模式1)
命令
;;
模式2)
命令
;;
*)
不符合以上模式执行的命令
esac

每个模式必须以右括号结束,命令结尾以双分号结束。

示例:根据位置参数匹配不同的模式

#!/bin/bash
case $1 in
start)
echo "start."
;;
stop)
echo "stop."
;;
restart)
echo "restart."
;;
*)
echo "Usage: $0 {start|stop|restart}"
esac # bash test.sh
Usage: test.sh {start|stop|restart}
# bash test.sh start
start.
# bash test.sh stop
stop.
# bash test.sh restart
restart.

上面例子是不是有点眼熟,在Linux下有一部分服务启动脚本都是这么写的。

模式也支持正则,匹配哪个模式就执行那个:

#!/bin/bash
case $1 in
[0-9])
echo "match number."
;;
[a-z])
echo "match letter."
;;
'-h'|'--help')
echo "help"
*)
echo "Input error!"
exit
esac
# bash test.sh 1
match number.
# bash test.sh a
match letter.
# bash test.sh -h
help
# bash test.sh --help
help

模式支持的正则有:*、?、[ ]、[.-.]、|。后面有章节单独讲解Shell正则表达式。

4.5 select语句

select是一个类似于for循环的语句。

select 变量 in 选项1 选项2; do
break
done

示例:

#!/bin/bash
select mysql_version in 5.1 5.6; do
echo $mysql_version
done
# bash test.sh
1) 5.1
2) 5.6
#? 1
5.1
#? 2
5.6

用户输入编号会直接赋值给变量mysql_version。作为菜单用的话,循环第二次后就不再显示菜单了,并不能满足需求。

在外面加个死循环,每次执行一次select就break一次,这样就能每次显示菜单了:

#!/bin/bash
while true; do
select mysql_version in 5.1 5.6; do
echo $mysql_version
break
done
done
# bash test.sh
1) 5.1
2) 5.6
#? 1
5.1
1) 5.1
2) 5.6
#? 2
5.6
1) 5.1
2) 5.6

如果再判断对用户输入的编号执行相应的命令,如果用if语句多分支的话要复杂许多,用case语句就简单多了。

#!/bin/bash
PS3="Select a number: "
while true; do
select mysql_version in 5.1 5.6 quit; do
case $mysql_version in
5.1)
echo "mysql 5.1"
break
;;
5.6)
echo "mysql 5.6"
break
;;
quit)
exit
;;
*)
echo "Input error, Please enter again!"
break
esac
done
done
# bash test.sh
1) 5.1
2) 5.6
3) quit
Select a number: 1
mysql 5.1
1) 5.1
2) 5.6
3) quit
Select a number: 2
mysql 5.6
1) 5.1
2) 5.6
3) quit
Select a number: 3

如果不想用默认的提示符,可以通过重新赋值变量PS3来自定义。这下就比较完美了!

Shell从入门到精通进阶之四:流程控制的更多相关文章

  1. 【java从入门到精通】day08-java流程控制-用户交互Scanner--顺序结构--选择结构

    1.java流程控制 Scanner对象: Java提供了一个工具类,可以获取用户的输入 java.until.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入 基本语 ...

  2. shell从入门到精通进阶之一:Shell基础知识

    1.1 简介 Shell是一个C语言编写的脚本语言,它是用户与Linux的桥梁,用户输入命令交给Shell处理,Shell将相应的操作传递给内核(Kernel),内核把处理的结果输出给用户. 下面是处 ...

  3. Shell从入门到精通进阶之三:表达式与运算符

    3.1 条件表达式 表达式 示例 [ expression ] [ 1 -eq 1 ]  ` expression ` ` 1 -eq 1 ` test expression test 1 -eq 1 ...

  4. Shell从入门到精通进阶之二:Shell字符串处理之${}

    上一章节讲解了为什么用${}引用变量,${}还有一个重要的功能,就是文本处理,单行文本基本上可以满足你所有需求. 2.1 获取字符串长度 # VAR='hello world!' # echo $VA ...

  5. 【java从入门到精通】day10-Java流程控制2-switch多选择结构

    1.switch多选择结构 switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支. switch语句中的变量类型可以是: byte.short.int或者char 从j ...

  6. python入门篇之介绍和流程控制(一)

    Python入门 一.第一句python代码 很多语言的第一句python代码都是以“你好,世界”开始的,那么我们的python也是如此. 在 /home/dev/ 目录下创建 hello.py 文件 ...

  7. FFmpeg从入门到精通——进阶篇,SEI那些事儿

    前言 在直播应用的开发过程中,如果把主播端消息事件传递到观众端,一般会以Instant Messaging(即时通讯)的方式传递过去,但因为消息分发通道和直播通道是分开的,因此消息与直播音视频数据的同 ...

  8. Jmeter(三十四) - 从入门到精通进阶篇 - 参数化(详解教程)

    1.简介 前边三十多篇文章主要介绍的是Jmeter的一些操作和基础知识,算是一些初级入门的知识点,从这一篇开始我们就来学习Jmeter比较高级的操作和深入的知识点了.今天这一篇主要是讲参数化,其实前边 ...

  9. Shell从入门到精通

    熟悉基本shell操作不仅是运维的基本功,对于开发来说也是多多益善,我在学习的过程中,总结了十个练手的小demo,并附上涉及的知识点,仅供娱乐. 1. 多线程ping监控,检查同一网段的IP是否连通 ...

随机推荐

  1. bzoj 2500 幸福的道路 树上直径+set

    首先明确:树上任意一点的最长路径一定是直径的某一端点. 所以先找出直径,求出最长路径,然后再求波动值<=m的最长区间 #include<cstdio> #include<cst ...

  2. BZOJ_2956_模积和_数学

    BZOJ_2956_模积和_数学 Description 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j. Input 第一行两个数 ...

  3. 从MVC和三层架构说到SSH整合开发

    相信很多人都认同JavaWeb开发是遵从MVC开发模式的,遵从三层架构进行开发的,是的,大家都这么认同.但是相信大家都会有过这样一个疑问,if(MVC三层模式==三层架构思想)out.println( ...

  4. Hibernate-ORM:05.Hibernate中的list()和iterator()

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- Hibernate中查多条(全部)使用list()或iterator() 本篇介绍: 1.如何使用list() ...

  5. ThreadLocal的应用与实现原理

    本文对ThreadLocal的分析基于JDK 8. 本文大纲 1. ThreadLocal快速上手 2. ThreadLocal应用场景 3. TheadLocal set与get方法简析 4. Th ...

  6. 通过模拟JDK中的动态代理,由浅入深讲解动态代理思想.

    目录 场景引入 动态代理引入 动态代理进阶 总结 个人认为动态代理在设计模式中算是比较难的, 本篇文章将从无到有, 从一个简单代码示例开始迭代, 逐步深入讲解动态代理思想. 场景引入 假设现在有一个坦 ...

  7. spring boot整合spring5-webflux从0开始的实战及源码解析

    上篇文章<你的响应阻塞了没有?--Spring-WebFlux源码分析>介绍了spring5.0 新出来的异步非阻塞服务,很多读者说太理论了,太单调了,这次我们就通过一个从0开始的实例实战 ...

  8. Python基础 列表介绍、使用

    第3章 学习目标: 列表是什么以及如何使用列表元素.列表让你能够在一个地方存储成组的信息,其中可以只包含几个元素,也可以包含数百万个元素.列表是新手可直接使用的最强大的Python功能之一,它融合了众 ...

  9. jQuery实现全选、反选和不选功能

    HTML 我们的页面上有一个歌曲列表,列出多行歌曲名称,并匹配复选框供用户选择,并且在列表下方有一排操作按钮. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 <ul id=&q ...

  10. ArcGIS API for JavaScript 4.9 & 3.26 发布与新特性

    应该是中文首发?我只想说:更新太TMD快了 QAQ Part I -- JsAPI 4.9 主题1:在2D中默认启用WebGL渲染 在要素图层.CSV图层.流图层中是使用WebGL渲染的,这个任务由M ...