控制结构

概述

每一个程序如何运行,其中的数据是如何进行传递的,是通过控制结构来实现的,程序的控制结构是指以某种顺序执行的一系列动作,用于解决某个问题。无论多么复杂的算法,均可通过顺序、选择、循环 3 中基本机构构造出来。每种结构仅有一个执行开始的入口以及执行结束的出口。由着 3 中基本机构组成的多层嵌套程序称为结构化程序

控制结构中的“条件语句”详见 条件语句与运算

一:顺序结构

按照语句编写的顺序自上到下主句执行就是顺序结构

二:选择结构

if…;then…;fi 选择结构

对某语句进行判断,判断完成后执行某动作。i.e.如果条件语句 1 为真,那么执行分支 1 语句,否则执行条件语句 2,如果条件语句 2 为真,那么执行分支 2 语句,否则执行条件语句 3,如果条件语句 3 为真,那么执行分支 3 语句,……….(可无限循环),否则执行分支 n 语句

语法结构:

###单分支:如果“条件语句”为真,则执行“分支”
if 条件语句;then
   分支
fi
###双分支:如果“条件语句”为真,则执行“分支1”,否则执行“分支2”
if 条件语句; then
   分支1
else
   分支2
fi
###多分支:如果“条件语句”为真,则执行“分支1”,否则如果“条件语句2”为真,则执行“分支2”...以此类推
if 条件语句1; then
   分支1
elif 条件语句2; then
   分支2
elif 条件语句3; then
   分支3
...
else
   分支n;
fi

case 判断结构

给定一个变量,当变量的值为某值时,执行某程序

语法结构:

case  $参数变量 in
"变量值1"# 变量值用双引号括起来,关键字用小括号括起来
    程序段1     # 对应的逻辑
;;             # 每个类别结尾使用两个连续的分号来处理
"变量值2"    程序段2
;;
"变量值3"    程序段3
;;
*)             # 最后一个位置参数值会用*来代替所有其他值
    程序段4
;;
esac

三:循环控制语句

for 循环结构

持续对一个变量赋值之后并执行相关命令,直到变量使用完所有给定的值

语法结构

for VAR in VALs;do # do表示循环开始,VALs的内容逐个赋值给VAR变量
    循环体 # 语句1,语句2。。。。等等,可以引用VAR变量
done # done表示循环结束。

可以简写为:

for VAR in VALs; do 循环体; done

VALs 是一个列表,默认以空格分割,每个 VAL 赋值给变量 VAR 一次,就执行一次循环体任务,直到列表中的值全部赋值完成,则结束循环。

VALs 的取值方式:

  • Val1 Val2.....ValN # 每个值中间以空格分割
  • seq NUM1 NUM2 # 使用 seq 命令打印出从 NUM1 到 NUM2 两个数之间的所有整数作为列表中的值,NUM 可以使用变量。如果运行脚本时候带参数了,则 NUM 变为参数的位置,引用第 NUM1 个位置到第 NUM2 个位置的参数
    • 语法格式:seq [options] NUM1 增量 NUM2 # 用法见下面 shift 命令讲解
  • {NUM1..NUM2} # 从 NUM1 到 NUM2 之间的所有整数作为值,NUM 不可以使用变量
  • $* 或 $@ # 通过位置变量来使用 VALs。列表中的内容可以在运行脚本的时候就给定,比如./XXX.sh 5 10 11,其中 5,10,11 就是脚本的参数然后通过位置变量在列表中引用
  • /XX/YY/\* # /XX/YY 目录下的所有文件

EXAMPLE:

for userName in desistdaydream zhangna;do #如果需要换行的语句写在一行上,中间需要加;分好
 useradd -m $userName #给变量赋值desistdaydream,然后执行useradd命令,再给变量赋值zhangna,然后执行useradd命令,列表内容全部赋值完成,结束循环。
done

while 循环结构

条件语句为真(即 0),则执行循环体,直到条件语句为假(即非 0),则退出循环(注意:while 的循环体中最好加上一行代码,对条件语句中的变量赋值,以便每次执行循环之后,条件测试中的变量变成一个新值,否则极有可能陷入无限循环)循环体中可以使用 elif 进行多分支管理

语法结构 1

while 条件语句;do
    循环体
done

EXAMPLE

while [ $i -le 100 ];do #判断$i是否小于等于100,如果判断结果$?的值为0那么执行下面两行代码,否则执行done语句退出循环
  let sum+=$i  #给sum变量赋值,值为$sum+$i
  let i++   #i值+1
done
echo $sum   #输出1到100的和

语法结构 2 # read 通过输入重定向,把 FILE 文件内的的第一行所有的内容赋值给变量 VAR,循环体内的命令一般包含对变量 VAR 的处理;然后循环处理第二行、第三行。。。一直到最后一行。当 read 从文件 FILE 中读到内容时,退出状态为 0,循环继续执行,当 read 从文件中读完最后一行后,下次便没有内容可读了,此时 read 的退出状态为非 0,循环才会退出。

while read VAR; do
  循环体
done < FILE

EXAMPLE # 取出来 passwd 文件中的每一行,cut 出来每一行的第一个字段

while read line; do
  cut -d: -f1 $line
done < /etc/passwd

语法结构 3 # COMMAND 命令的输出作为变量 VAR 的值,通过 read 循环的输入

COMMAND | while read VAR; do
    循环体
done

EXAMPLE # 取出来 passwd 文件中的每一行,cut 出来每一行的第一个字段

cat /etc/passwd | while read line; do
  cut -d: -f1 $line
done

for 和 while 的区别

  • for:
    • 列表中的数值赋值一次执行一次循环,直到列表全部赋值完毕
    • 循环体对以空格为分隔符的字符串进行操作
  • while:
    • 条件语句判断一次,执行一次循环,直到条件判断为假
    • 循环体对每一行进行操作

select 循环结构

select in 循环用来增强交互性,它可以显示出带编号的菜单,用户输入不同的编号就可以选择不同的菜单,并执行不同的功能。

select VAR in ValueList; do
    循环体
done

运行到 select 语句后,ValueList(值列表) 中的内容会以菜单的形式显示出来,用户输入菜单编号,就表示选中了某个值,这个值就会赋给变量 VAR,然后再执行循环体中的语句。

每次循环时 select 都会要求用户输入菜单编号,并使用环境变量 ${PS3} 的值作为提示符,${PS3} 的默认值为 #?,修改 PS3 的值就可以修改提示符。

如果用户输入的菜单编号不在范围之内,或者输入一个空值(什么也不输入,直接回车),那么就会给 VAR 赋一个空值,并且重新显示一遍菜单。

Note:select 是无限循环(死循环),输入空值,或者输入的值无效,都不会结束循环,只有遇到 break 语句,或者按下 Ctrl+D 组合键才能结束循环

select in 通常和 case in 一起使用,在用户输入不同的编号时可以做出不同的反应。

EXAMPLE

#!/bin/bash
echo "What is your favourite OS?"
select name in "Linux" "Windows"
do
    echo $name
done
echo "You have selected $name"

运行效果:

~]# bash select.sh
What is your favourite OS?
1) Linux
2) Windows
#? 1
Linux
#? ^d
You have selected Linux

#? 用来提示用户输入菜单编号;^D 表示按下 Ctrl+D 组合键,它的作用是结束 select in 循环。

until 循环结构(可有可无)

条件测试为假,则执行循环体,与 while 循环相反,其余内容一样

四、其余相关知识点

shift:位置参数轮替,在运行脚本的时候输入 N 个参数,每使用一次 shift 就舍弃掉一个位置参数,参数就是 for 循环中列表的内容

例:

./XXX.sh 5 10 8 4       # 实现 5+10+8+4 求和
#!/bin/bash
declare -i sum=0
for i in `seq 1 $#`;do  # 列表中的内容是运行脚本的时候输入的参数的第1个数到第4个数,$#用于显示一共有几个参数
        sum+=$1         # $1引用5 10 8 4 中的第一个参数,计算sum=sum+运行脚本时候输入的第一个参数
        shift           # 把第一个位置的参数踢掉,让第二位参数变成第一位
done                    # 执行完一次循环之后第一位置参数5被踢掉,10变成第一位参数,以此类推
echo $sum

exit 命令退出模式:直接输入 exit X(表示该脚本直接结束,返回执行状态代码 X)

read 命令

该命令可以一次读取多个变量的值,变量和输入的值都需要使用空格隔开。在 read 命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量 REPLY

read [选项] VarName1 VarName2 # 从键盘读取变量的值,通常用在 shell 脚本中与用户进行交互的场合。 OPTIONS

  • -t # 指定读取值时等待的时间(秒)
  • -p # 指定读取值时的提示符

EXAMPLE

  • read -p "输入一个数:" first last # 输入完整个命令后,界面显示“输入一个数:”,然后可以自行输入信息,输入的第一个信息赋值给 first 变量,空格后的其余信息赋值给 last 变量,效果如下所示
~]# read -p "输入一个数:" first last
输入一个数:123 321
~]# echo $firest $last
321

最后修改 July 5, 2024: shell, docker (876d0a08)