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

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. bzoj4904 [Ctsc2017]最长上升子序列

    我们发现他让求的东西很奇怪,于是通过某D开头定理,我们转化为前m位的序列用k个不上升子序列最多能覆盖多少.数据范围小的时候可以网络流做,但是这道题显然不支持网络流的复杂度.然后有一个奇怪的东西叫杨氏矩 ...

  2. BZOJ_1579_[Usaco2009 Feb]Revamping Trails 道路升级_分层图最短路

    BZOJ_1579_[Usaco2009 Feb]Revamping Trails 道路升级_分层图最短路 Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M ...

  3. oracle服务的一些问题,先发2个,以后慢慢添加~~

    OracleOraDb11g_home1TNSLister服务启动后停止 解决办法: 1. 修改文件C:\app\zhuwei\product\11.1.0\db_1\NETWORK\ADMIN\li ...

  4. CentOS7解决firefox无法启用ibus中文输入的问题

    最近换电脑,要换掉使用了6年的旧环境,开始折腾重装系统: 下了minimal版本的CentOS7.4,然后开始一点点装想用的东西,多少找到一点十年前折腾LFS的感觉:然后竟然被输入法拌住了半天,事后回 ...

  5. Android LayoutInflater源码解析:你真的能正确使用吗?

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 好久没写博客了,最近忙着换工作,没时间写,工作刚定下来.稍后有时间会写一下换工作经历.接下来进入本篇主题,本来没想写LayoutInflater的 ...

  6. 再谈腾讯云centos服务器不能登录的解决过程

    上篇文章谈到腾讯云centos服务器不能登录,通过查看监控信息,cpu使用过高,再腾讯云页面使用VNC方式直接登录,然后根据提示信息,关闭导致内存溢出的进程,从而解决问题. 1 问题再现 昨天刚解决了 ...

  7. ConstraintLayoutDemo【约束性布局知识梳理】【基于1.1.3】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 在较新版本的Android Studio中新建项目默认使用 ConstraintLayout进行布局的. ConstraintLay ...

  8. .NETCore 快速开发做一个简易商城

    介绍 上一篇介绍 <.NETCore 基于 dbfirst 体验快速开发项目>,讲得不太清楚有些多人没看懂.这次吸取教训,将一个简易商城做为案例,现实快速开发. 本案例用于演示或学习,不具 ...

  9. 微信小游戏爆款秘笈 数据库MongoDB攻略篇

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB 发表于云+社区专栏 随着微信小游戏的爆发,越来越多开发者关注到MongoDB与小游戏业务的契合度. ...

  10. 使用myeclipse修改项目映射路径

    这里主要做下记录,找到myeclipse中对项目路径进行查看以及修改的地址 如图 点击项目右键 实例url:http://localhost:8080/myFirstServlet/one 对应路径中 ...