1.实验目的与要求
- 掌握for语句的使用
- 掌握while、continue、until语句的使用
- 掌握循环语句的使用
- 熟悉循环语句的嵌套
2.实验平台
实验室安装的实验环境(Linux操作系统)和头歌(www.educoder.net)实验平台(课程实验)
3.实验内容
- 练习for语句的使用
- 练习while、continue、until语句的使用
- 练习循环语句的嵌套
4.实验详细内容、步骤
任务描述
本关任务:掌握 for 循环语句以及 seq 命令在 for 循环中的使用。
相关知识
在实际编程中,需要重复一组命令直至达到某个特定条件,比如处理某个目录下的所有文件、系统上的所有用户或是某个文本文件中的所有行。因此诞生了 for 循环、while 循环、util 循环这样的语句。本关首先给大家介绍 for 循环语句的使用。
for循环基本语法:
- for var in item1 item2 ... itemN
- do
- command1
- command2
- ...
- commandN
- done
或者写成一行:
- for var in item1 item2 ... itemN; do command1; command2… done;
for循环语法演变:
【语法一】遍历普通列表, 在 shell 中以空格隔开的 item ,默认将其视为列表。
- for 变量 in 值1 值2 值3..
- do
- 程序块儿
- done
【实例1】输出五次 uptime:
- #!/bin/bash
- for i in 1 2 3 4 5
- do
- echo "$i-->$(uptime)"
- done
输出结果如下:
- [root@master-01-k8s opt]# bash a.sh
- 1--> 16:34:39 up 236 days, 23:41, 2 users, load average: 0.53, 0.46, 0.49
- 2--> 16:34:39 up 236 days, 23:41, 2 users, load average: 0.53, 0.46, 0.49
- 3--> 16:34:39 up 236 days, 23:41, 2 users, load average: 0.53, 0.46, 0.49
- 4--> 16:34:39 up 236 days, 23:41, 2 users, load average: 0.53, 0.46, 0.49
- 5--> 16:34:39 up 236 days, 23:41, 2 users, load average: 0.53, 0.46, 0.49
【语法二】for 遍历 "命令返回结果的数组",反引号 ` ` 或者 $()
表示命令返回结果列表。
- for 变量 in `命令`
- do
- 程序块儿
- done
【实例2】遍历 /home 目录下的文件。
- #!/bin/bash
- for i in $(ls /home)
- do
- echo "当前目录下的文件为 $i"
- done
输出结果为:
- 当前目录下的文件为 admin
- 当前目录下的文件为 aliyun
- 当前目录下的文件为 aliyun_metric-server2.yaml
- 当前目录下的文件为 git
- 当前目录下的文件为 pdl
- 当前目录下的文件为 prometheus
- 当前目录下的文件为 work
- 当前目录下的文件为 zsp
【语法三】c 语言风格的循环语句:
- #!/bin/bash
- for (( 初始值; 循环控制; 变量变化 ))
- do
- 程序块儿
- done
shell 的 for 命令跟 C 语言类似,有一个用来指明变量的特定方法,一个必须保持成立才能继续迭代的条件,以及另一个在每个迭代中改变变量的方法。当指定的条件不成立时, for 循环就会停止。条件等式通过标准的数学符号定义。
【实例3】
- #!/bin/bash
- # 注意双括号左右留有一个空格; i=1是变量赋值,不能多空格
- for (( i=1; i <= 10; i++ ))
- do
- echo "The next number is $i"
- done
这段代码产生了一个简单的迭代循环,其中变量 i 作为计数器。第一部分将一个默认值赋给该变量;中间的部分定义了循环重复的条件,当定义的条件不成立时, for 循环就停止迭代;最后一部分定义了迭代的过程。在每次迭代之后,最后一部分中定义的表达式会被执行。在本例中,i 变量会在每次迭代后增 1。 执行结果:
- The next number is 1
- The next number is 2
- The next number is 3
- The next number is 4
- The next number is 5
- The next number is 6
- The next number is 7
- The next number is 8
- The next number is 9
- The next number is 10
seq命令
seq 命令用于产生从某个数到另外一个数之间的所有整数列表。 常见用法如下:
- seq [选项]... 尾数
- seq [选项]... 首数 尾数
- seq [选项]... 首数 增量 尾数
【实列4】采用 seq 命令,结合 for 循环,打印 1 到 10 之间的所有整数。
- for i in `seq 1 10`
- do
- echo "第$i个数是 $i"
- done
输出结果如下:
- 第1个数是 1
- 第2个数是 2
- 第3个数是 3
- 第4个数是 4
- 第5个数是 5
- 第6个数是 6
- 第7个数是 7
- 第8个数是 8
- 第9个数是 9
- 第10个数是 10
编程要求
在右侧编辑器 Begin-End 区间补充代码,使用 for 循环和 seq 命令打印 1 到 10 之间的奇数。
任务描述
本关任务:掌握 while 命令的使用方法。
相关知识
三种运算符号
- 双小括号
(( ))
是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令,具体用法请见图 1; []
是 Shell 内置关键字,它和 test 命令类似,可用于判断某个条件是否为真。可用于字符串、数值和文件的测试;[[ ]]
是 Shell 内置关键字,它和 test 命令类似,也用来检测某个条件是否成立。相比[]
,[[]]
功能更强大,支持正则表达式和逻辑运算。
while循环语法
while 循环是 Shell 脚本中最简单的一种循环,当条件满足时,while 重复地执行一组语句;当条件不满足时,就退出 while 循环。
while 循环的用法如下:
- while condition # 此处 condition 可以是(())、[]、[[]]判断结果
- do
- statements
- done
语法说明: condition 表示判断条件,statements 表示要执行的语句(可以只有一条,也可以有多条),do 和 done 都是 Shell 中的关键字。
while 循环的执行流程为:
- 先对 condition 进行判断,如果该条件成立,就进入循环,执行 while 循环体中的语句,也就是 do 和 done 之间的语句。这样就完成了一次循环;
- 每一次执行到 done 的时候,都会重新判断 condition 是否成立。如果成立,就进入下一次循环,继续执行 do 和 done 之间的语句;如果不成立,就结束整个 while 循环,执行 done 后面的其它 Shell 代码;
- 如果一开始 condition 就不成立,那么程序就不会进入循环体,do 和 done 之间的语句就没有执行的机会。
注意:在 while 循环体中必须有相应的语句使得 condition 越来越趋近于“不成立”,只有这样才能最终退出循环,否则 while 就成了死循环,会一直执行下去,永无休止。
【实例1】每两秒钟向 /opt/uptime.log 文件中追加系统负载情况。
- #!/bin/bash
- while [ 1 ] # [ 1 ]和 true 一样,只是前面2边需要有空格
- do
- uptime >>/tmp/uptime.log # >>是重定向符号
- sleep 2
- done
- #注:
- #uptime 用于查看系统负载
- #sleep 2 表示程序睡眠一秒
【实例2】计算 1+2...100 的和。
- 方式一:
- #!/bin/sh
- SUM=0
- I=1
- while [ $I -le 100 ] #[]中需要变量取值符号"$",而且大于小于只能用"-le"
- do
- ((SUM+=I))
- let I++
- done
- echo $SUM
- -------------------------------------------------------------------------------------------------
- 方式二:
- #!/bin/sh
- SUM=0
- I=1
- while ((I<=100)) #(())中可以不要变量取值符号,大于小于是可以直接用
- do
- ((SUM+=I))
- ((I++))
- done
- echo $SUM
- -------------------------------------------------------------------------------------------------
- 方式三:
- #!/bin/sh
- SUM=0
- I=100
- ((SUM=I*(I+1)/2))
- echo $SUM
循环中断和不中断
有些程序执行时,用户希望程序一直运行。在运行【实列1】中脚本时候,我们可以使用 sh shell.sh &
来代替 sh shell.sh
让其一直在后台执行。当我们遇到脚本死循环的时候,也可以使用 Ctrl+z 的方式强制中断。 常用的中断和不中断技巧如下:
- 使用"sh shell.sh &"命令 ,即使用 & 在后台运行
- 使用"nohup shell.sh &"命令,即使用 nohup 加 & 在后台运行脚本
- 利用 screen 保持会话,然后再执行脚本,即使用 screen 保持当前会话
- 后台运行的知识:
- sh shell.sh & 脚本 shell.sh 放在后台执行
- Ctrl+c 停止执行当前脚本或任务
- Ctrl+z 暂停执行当前脚本
- jobs 查看当前执行的脚本或任务
- bg 将当前脚本或任务放到后台执行
- kill 关闭当前脚本任务,即以"kill %号码"的形式关闭进程,任务号通过 jobs 获得
- fg 将当前的脚本或任务放到前台执行,若有多任务,则"fg 号码"调出相应的任务编号
【实例3】实际操作效果如下:
- [centos@mycentos shell]$ sh 2.sh & #后台运行
- [1] 2988
- [centos@mycentos shell]$ jobs #查看任务数
- [1]+ Running sh 2.sh &
- [centos@mycentos shell]$ kill %1 #关闭进程为1的进程
- [centos@mycentos shell]$ jobs
- [1]+ Terminated sh 2.sh #程序已经被关闭
大家可以根据实例 3 在命令行中自己试验一下。
任务描述
本关任务:掌握 until 循环语句的使用。
相关知识
until语句语法
unti 循环和 while 循环恰好相反;当判断条件不成立时才进行循环,一旦判断条件成立,就终止循环。语法如下:
- until condition
- do
- statements
- done
跟 while 一样,condition 表示判断条件,statements 表示要执行的语句(可以只有一条,也可以有多条),do 和 done 都是 Shell 中的关键字。
until 循环的执行流程为:
- 先对 condition 进行判断,如果该条件不成立,就进入循环,执行 until 循环体中的语句(do 和 done 之间的语句),这样就完成了一次循环;
- 每一次执行到 done 的时候,都会重新判断 condition 是否成立。如果不成立,就进入下一次循环,继续执行循环体中的语句;如果成立,就结束整个 until 循环,执行 done 后面的其它 Shell 代码;
- 如果一开始 condition 就成立,那么程序就不会进入循环体,do 和 done 之间的语句就没有执行的机会。
注意:在 until 循环体中必须有相应的语句使得 condition 越来越趋近于“成立”,只有这样才能最终退出循环,否则 until 就成了死循环,会一直执行下去,永无休止。
【实例1】
- #!/bin/bash
- i=0
- until [[ "$i" -gt 5 ]] #大于5
- do
- let "square=i*i"
- echo "$i * $i = $square"
- let "i++"
- done
执行流程:直到 i 大于 5 的时候,循环退出;当变量 i 小于等于 5 的时候,执行 do 和 done 代码块中的命令,这里的 let 是 shell 的内置计算命令。 输入出结果如下:
- [root@work02 opt]# bash a.sh
- 0 * 0 = 0
- 1 * 1 = 1
- 2 * 2 = 4
- 3 * 3 = 9
- 4 * 4 = 16
- 5 * 5 = 25
任务描述
本关任务:掌握 shell 语句中的循环嵌套的方法和使用场景,输出系统中的可执行文件。
相关知识
循环语句可以在循环内使用任意类型的命令,包括其他循环命令。这种循环叫作嵌套循环(nested loop)。注意,在使用嵌套循环时,你是在迭代中使用迭代,与命令运行的次数是乘积关系。不注意这点的话,有可能会在脚本中造成问题。
for-for循环嵌套
这里有个在 for 循环中嵌套 for 循环的简单例子。
【实例1】
- #!/bin/bash
- # nesting for loops
- for (( a = 1; a <= 3; a++ ))
- do
- echo "Starting loop $a:"
- for (( b = 1; b <= 3; b++ ))
- do
- echo " Inside loop: $b"
- done
- done
执行脚本输出结果为:
- Starting loop 1:
- Inside loop: 1
- Inside loop: 2
- Inside loop: 3
- Starting loop 2:
- Inside loop: 1
- Inside loop: 2
- Inside loop: 3
- Starting loop 3:
- Inside loop: 1
- Inside loop: 2
- Inside loop: 3
这个被嵌套的循环(也称为内部循环,inner loop)会在外部循环的每次迭代中遍历一次它所有的值。注意,两个循环的 do 和 done 命令没有任何差别。bash shell 知道当第一个 done 命令执行时,是指内部循环而非外部循环。
for-while循环嵌套
在混用循环命令时也一样,比如在 while 循环内部放置一个 for 循环。
【实例2】
- #!/bin/bash
- # placing a for loop inside a while loop
- var1=5
- while [ $var1 -ge 0 ]
- do
- echo "Outer loop: $var1"
- for (( var2 = 1; $var2 < 3; var2++ ))
- do
- var3=$[ $var1 * $var2 ]
- echo " Inner loop: $var1 * $var2 = $var3"
- done
- var1=$[ $var1 - 1 ]
- done
执行脚本输出结果为:
- Outer loop: 5
- Inner loop: 5 * 1 = 5
- Inner loop: 5 * 2 = 10
- Outer loop: 4
- Inner loop: 4 * 1 = 4
- Inner loop: 4 * 2 = 8
- Outer loop: 3
- Inner loop: 3 * 1 = 3
- Inner loop: 3 * 2 = 6
- Outer loop: 2
- Inner loop: 2 * 1 = 2
- Inner loop: 2 * 2 = 4
- Outer loop: 1
- Inner loop: 1 * 1 = 1
- Inner loop: 1 * 2 = 2
- Outer loop: 0
- Inner loop: 0 * 1 = 0
- Inner loop: 0 * 2 = 0
until-while循环嵌套
如果真的想挑战脑力,可以混用 until 和 while 循环。 【实列3】
- #!/bin/bash
- # using until and while loops
- var1=3
- until [ $var1 -eq 0 ]
- do
- echo "Outer loop: $var1"
- var2=1
- while [ $var2 -lt 5 ]
- do
- var3=$(echo "scale=4; $var1 / $var2" | bc)
- echo " Inner loop: $var1 / $var2 = $var3"
- var2=$[ $var2 + 1 ]
- done
- var1=$[ $var1 - 1 ]
- done
执行脚本输出结果为:
- Outer loop: 3
- Inner loop: 3 / 1 = 3.0000
- Inner loop: 3 / 2 = 1.5000
- Inner loop: 3 / 3 = 1.0000
- Inner loop: 3 / 4 = .7500
- Outer loop: 2
- Inner loop: 2 / 1 = 2.0000
- Inner loop: 2 / 2 = 1.0000
- Inner loop: 2 / 3 = .6666
- Inner loop: 2 / 4 = .5000
- Outer loop: 1
- Inner loop: 1 / 1 = 1.0000
- Inner loop: 1 / 2 = .5000
- Inner loop: 1 / 3 = .3333
- Inner loop: 1 / 4 = .2500
外部的 until 循环以值 3 开始,并继续执行到值等于 0。内部 while 循环以值 1 开始并一直执行,只要值小于 5。每个循环都必须改变在测试条件中用到的值,否则循环就会无止尽进行下去。
控制循环
你可能会想,一旦启动了循环,就必须苦等到循环完成所有的迭代,并不是这样的。有两个命令能帮我们控制循环内部的情况: break 命令和 continue 命令,每个命令在如何控制循环的执行方面有不同的用法。下面将介绍如何使用这些命令来控制循环。
- break 命令:跳出单个循环在 shell 执行 break 命令时,它会尝试跳出当前正在执行的循环,请见【实例4】。
【实列4】
- #!/bin/bash
- # breaking out of a for loop
- for var1 in 1 2 3 4 5 6 7 8 9 10
- do
- if [ $var1 -eq 5 ];then
- break
- fi
- echo "Iteration number: $var1"
- done
- echo "The for loop is completed"
执行脚本输出结果为:
- Iteration number: 1
- Iteration number: 2
- Iteration number: 3
- Iteration number: 4
- The for loop is completed
for 循环通常都会遍历列表中指定的所有值。但当满足 if-then 的条件时,shell 会执行 break 命令,停止 for 循环。
- continue 命令:continue 命令可以提前中止某次循环中的命令,但并不会完全终止整个循环。可以在循环内部设置 shell 不执行命令的条件。这里有个在 for 循环中使用 continue 命令的简单例子。
【实例5】
- #!/bin/bash
- # using the continue command
- for (( var1 = 1; var1 < 15; var1++ ))
- do
- if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
- then
- continue
- fi
- echo "Iteration number: $var1"
- done
执行脚本输出结果为:
- Iteration number: 1
- Iteration number: 2
- Iteration number: 3
- Iteration number: 4
- Iteration number: 5
- Iteration number: 10
- Iteration number: 11
- Iteration number: 12
- Iteration number: 13
- Iteration number: 14
执行说明:
- 当 if-then 语句的条件被满足时(值大于 5 且小于 10),shell 会执行 continue 命令,跳过此次循环中剩余的命令,但整个循环还会继续。当 if-then 的条件不再被满足时,一切又回到正轨;
- 也可以在 while 和 until 循环中使用 continue 命令,但要特别小心。记住,当 shell 执行 continue 命令时,它会跳过剩余的命令。如果你在其中某个条件里对测试条件变量进行增值,问题就会出现。
编程要求
背景:当你从命令行中运行一个程序的时候,Linux 系统会搜索一系列目录来查找对应的文件。
在右侧编辑器 Begin-End 区间补充代码,输出变量 dir 的可执行文件有哪些。
编程思路:
- 首先是创建一个 for 循环,对环境变量 dir 中的目录进行迭代。处理的时候别忘了设置 IFS 分隔符。(
IFS=
:
,即指定 shell 的分割符为:
)- i. IFS=:
- ii. for folder in $dir
- iii. do
- 现在你已经将各个目录存放在了变量
$folder
中,可以使用另一个 for 循环来迭代特定目录中的所有文件。- i. for file in $folder/*
- ii. do
- 最后一步是检查各个文件是否具有可执行权限,你可以使用 if-then 测试功能来实现。
- i. if [ -x $file ]
- ii. then
- iii. echo " $file"
- iv. fi
任务描述
本关任务:利用for循环实现打印符合要求的5行@号:第1行打印1个@,第2行打印2个@,第3行打印3个@,第4行打印4个@,第5行打印5个@。
相关知识
为了完成本关任务,你需要掌握:for循环的基本语句格式。
案例演示1
假设有4个学生,分别是张三,李四,王五,赵六,如果每一行都按“学生:...”之类的样式输出,则可以如此撰写程序:
- #!/bin/bash
- for stud in 张三 李四 王五 赵六
- do
- echo "学生:$stud“
- done
案例演示2
- #!/bin/bash
- read -p "请输入一个数字,程序将计算从1到这个数字间所有数字的和:" num
- s=0
- for ((i=1;i<=$num;i=i+1))
- do
- s=$(($s+$i))
- done
- echo "1到$num的所有数字的和是:$s"
编程要求
根据要求,在右侧编辑器补充代码,利用for循环实现打印符合要求的5行@号:第1行打印1个@,第2行打印2个@,第3行打印3个@,第4行打印4个@,第5行打印5个@。
测试说明
平台会对你编写的代码进行测试:
预期输出: @
@@
@@@
@@@@
@@@@@
任务描述
本关任务:利用for循环实现求Fibonacci数列的前20项的值。 1 1 2 3 5 8 13 21 ……
相关知识
为了完成本关任务,你需要掌握:for循环的基本语句格式。
案例演示1
假设有4个学生,分别是张三,李四,王五,赵六,如果每一行都按“学生:...”之类的样式输出,则可以如此撰写程序:
- #!/bin/bash
- for stud in 张三 李四 王五 赵六
- do
- echo "学生:$stud“
- done
案例演示2
- #!/bin/bash
- read -p "请输入一个数字,程序将计算从1到这个数字间所有数字的和:" num
- s=0
- for ((i=1;i<=$num;i=i+1))
- do
- s=$(($s+$i))
- done
- echo "1到$num的所有数字的和是:$s"
编程要求
根据要求,在右侧编辑器补充代码,利用for循环实现求Fibonacci数列的前20项的值。 1 1 2 3 5 8 13 21 ……
测试说明
平台会对你编写的代码进行测试:
预期输出: 1 1
2 3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181 6765
任务描述
本关任务:利用while语句来实现输出数字1到10。
相关知识
为了完成本关任务,你需要掌握:while语句的基本格式。
案例演示1
- #!/bin/bash
- s=0
- i=0
- while [ "$i" != "100" ]
- do
- i=$(($i+1))
- s=$(($s+$i))
- done
- echo "1到100的所有数字的和是:$s"
编程要求
根据要求,在右侧编辑器补充代码,利用while语句实现输出数字1到10。
测试说明
平台会对你编写的代码进行测试:
预期输出: 1
2
3
4
5
6
7
8
9
10
任务描述
本关任务:利用until语句来实现输出数字1到10。
相关知识
为了完成本关任务,你需要掌握:until语句的基本格式。
案例演示1
- #!/bin/bash
- s=0
- i=0
- until [ "$i" = "100" ]
- do
- i=$(($i+1))
- s=$(($s+$i))
- done
- echo "1到100的所有数字的和是:$s"
编程要求
根据要求,在右侧编辑器补充代码,利用until语句实现输出数字1到10。
测试说明
平台会对你编写的代码进行测试:
预期输出: 1
2
3
4
5
6
7
8
9
10