运维八一 运维八一
首页
运维杂记
编程浅尝
周积跬步
专栏
生活
关于
收藏
  • 分类
  • 标签
  • 归档
Source (opens new window)

运维八一

运维,运维!
首页
运维杂记
编程浅尝
周积跬步
专栏
生活
关于
收藏
  • 分类
  • 标签
  • 归档
Source (opens new window)
  • Go

  • Python

  • Shell

    • 前言

    • shell基础

    • Shell高级

      • Shell字符串处理之${}
      • Shell表达式与运算符
      • Shell流程控制
        • 1. if 语句
          • 1.1 单分支
          • 1.2 双分支
          • 1.3 多分支
        • 2. for 语句
        • 3. while 语句
        • 4. break 和 和 continue 语句
        • 5. case 语句
        • 6. select 语句
      • Shell函数与数组
      • shell正则表达式
    • shell三剑客

  • Java

  • Vue

  • 前端

  • 编程浅尝
  • Shell
  • Shell高级
lyndon
2022-11-06
目录

Shell流程控制

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

# 1. if 语句

格式:

if list; then list; [ elif list; then list; ] ... [ else list; ] fi
1

# 1.1 单分支

if 条件表达式; then
	命令
fi
1
2
3

示例:

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

# bash test.sh
yes
1
2
3
4
5
6
7
8

# 1.2 双分支

if 条件表达式; then
	命令
else
	命令
fi
1
2
3
4
5

示例 1:

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

# bash test.sh
no
1
2
3
4
5
6
7
8
9
10

示例 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
1
2
3
4
5
6
7
8

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

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

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

# 1.3 多分支

if 条件表达式; then
	命令
elif 条件表达式; then
	命令
else
	命令
fi
1
2
3
4
5
6
7

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

示例 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
1
2
3
4
5
6
7
8
9
10
11

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

示例 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
1
2
3
4
5
6
7
8
9

# 2. for 语句

格式:

for name [ [ in [ word ... ] ] ; ] do list ; done
1
for 变量名 in 取值列表; do
	命令
done
1
2
3

示例:

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

# bash test.sh
1
2
3
1
2
3
4
5
6
7
8
9

for 的语法也可以这么写:

#!/bin/bash
for i in "$@"; { # $@是将位置参数作为单个来处理
	echo $i
}

# bash test.sh 1 2 3
1
2
3
1
2
3
4
5
6
7
8
9

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

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

# bash test.sh
12
34
1
2
3
4
5
6
7
8

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

#!/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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

for 循环还有一种 C 语言风格的语法,常用于计数、打印数字序列:

for (( expr1 ; expr2 ; expr3 )) ; do list ; done
1
#!/bin/bash
for ((i=1;i<=5;i++)); do # 也可以 i--
	echo $i
done
1
2
3
4

示例 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
1
2
3
4
5
6
7
8

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

#!/bin/bash
URL="www.baidu.com www.sina.com www.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
1
2
3
4
5
6
7
8
9
10

# 3. while 语句

格式:

while list; do list; done
1
while 条件表达式; do
	命令
done
1
2
3

示例 1:

#!/bin/bash
N=0
while [ $N -lt 5 ]; do
	let N++
	echo $N
done

# bash test.sh
1
2
3
4
5
1
2
3
4
5
6
7
8
9
10
11
12
13

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

示例 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

示例 3:逐行处理文本

# 文本内容:
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

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

# 4. break 和 和 continue 语句

  • break 是终止循环。
  • continue 是跳出当前循环。

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

#!/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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

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

示例 2:举例子说明 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

当变量 N 等于 3 时,continue 跳过了当前循环,没有执行下面的 echo。 注意:continue 与 与 break 语句只能循环语句中使用。

# 5. case 语句

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

格式:

case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
1
case 模式名 in
模式 1)
	命令
;;
模式 2)
	命令
;;
*)
	不符合以上模式执行的命令
esac
1
2
3
4
5
6
7
8
9
10

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

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

#!/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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

上面例子是不是有点眼熟,在 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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

# 6. select 语句

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

格式:

select name [ in word ] ; do list ; done
1
select 变量 in 选项 1 选项 2; do
	break
done
1
2
3

示例:

#!/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
3) 5.1
4) 5.6
   #? 2
   5.6
5) 5.1
6) 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
4) 5.1
5) 5.6
6) quit
   Select a number: 2
   mysql 5.6
7) 5.1
8) 5.6
9) quit
   Select a number: 3
# 如果不想用默认的提示符,可以通过重新赋值变量 PS3 来自定义。这下就比较完美了!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
上次更新: 2022/11/06, 20:20:54
Shell表达式与运算符
Shell函数与数组

← Shell表达式与运算符 Shell函数与数组→

最近更新
01
ctr和crictl显示镜像不一致
03-13
02
alpine镜像集成常用数据库客户端
03-13
03
create-cluster
02-26
更多文章>
Theme by Vdoing | Copyright © 2015-2024 op81.com
苏ICP备18041258号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式