Linux操作系统实验七 Shell编程之循环程序编程

1.实验目的与要求

  1. 掌握for语句的使用
  2. 掌握while、continue、until语句的使用
  3. 掌握循环语句的使用
  4. 熟悉循环语句的嵌套

2.实验平台

实验室安装的实验环境(Linux操作系统)和头歌(www.educoder.net)实验平台(课程实验)

3.实验内容

  1. 练习for语句的使用
  2. 练习while、continue、until语句的使用
  3. 练习循环语句的嵌套

4.实验详细内容、步骤

任务描述

本关任务:掌握 for 循环语句以及 seq 命令在 for 循环中的使用。

相关知识

在实际编程中,需要重复一组命令直至达到某个特定条件,比如处理某个目录下的所有文件、系统上的所有用户或是某个文本文件中的所有行。因此诞生了 for 循环、while 循环、util 循环这样的语句。本关首先给大家介绍 for 循环语句的使用。

for循环基本语法:
  1. for var in item1 item2 ... itemN
  2. do
  3.     command1
  4.     command2
  5.     ...
  6.     commandN
  7. done

或者写成一行:

  1. for var in item1 item2 ... itemN; do command1; command2… done;
for循环语法演变:

【语法一】遍历普通列表, 在 shell 中以空格隔开的 item ,默认将其视为列表。

  1. for 变量 in 值1 值2 值3..
  2.   do
  3.    程序块儿
  4.   done

【实例1】输出五次 uptime:

  1. #!/bin/bash
  2. for i in 1 2 3 4 5 
  3. do 
  4.   echo "$i-->$(uptime)"
  5. done

输出结果如下:

  1. [root@master-01-k8s opt]# bash a.sh
  2. 1--> 16:34:39 up 236 days, 23:41,  2 users,  load average: 0.53, 0.46, 0.49
  3. 2--> 16:34:39 up 236 days, 23:41,  2 users,  load average: 0.53, 0.46, 0.49
  4. 3--> 16:34:39 up 236 days, 23:41,  2 users,  load average: 0.53, 0.46, 0.49
  5. 4--> 16:34:39 up 236 days, 23:41,  2 users,  load average: 0.53, 0.46, 0.49
  6. 5--> 16:34:39 up 236 days, 23:41,  2 users,  load average: 0.53, 0.46, 0.49

【语法二】for 遍历 "命令返回结果的数组",反引号 ` ` 或者 $() 表示命令返回结果列表。

  1. for 变量 in `命令`
  2.   do
  3.    程序块儿
  4.   done

【实例2】遍历 /home 目录下的文件。

  1. #!/bin/bash
  2. for i in $(ls /home)       
  3. do
  4.    echo "当前目录下的文件为 $i"
  5. done

输出结果为:

  1. 当前目录下的文件为 admin
  2. 当前目录下的文件为 aliyun
  3. 当前目录下的文件为 aliyun_metric-server2.yaml
  4. 当前目录下的文件为 git
  5. 当前目录下的文件为 pdl
  6. 当前目录下的文件为 prometheus
  7. 当前目录下的文件为 work
  8. 当前目录下的文件为 zsp

【语法三】c 语言风格的循环语句:

  1. #!/bin/bash
  2. for (( 初始值; 循环控制; 变量变化 ))
  3. do
  4.   程序块儿
  5. done

shell 的 for 命令跟 C 语言类似,有一个用来指明变量的特定方法,一个必须保持成立才能继续迭代的条件,以及另一个在每个迭代中改变变量的方法。当指定的条件不成立时, for 循环就会停止。条件等式通过标准的数学符号定义。

【实例3】

  1. #!/bin/bash
  2. # 注意双括号左右留有一个空格; i=1是变量赋值,不能多空格
  3. for (( i=1; i <= 10; i++ )) 
  4. do
  5.     echo "The next number is $i"
  6. done

这段代码产生了一个简单的迭代循环,其中变量 i 作为计数器。第一部分将一个默认值赋给该变量;中间的部分定义了循环重复的条件,当定义的条件不成立时, for 循环就停止迭代;最后一部分定义了迭代的过程。在每次迭代之后,最后一部分中定义的表达式会被执行。在本例中,i 变量会在每次迭代后增 1。 执行结果:

  1. The next number is 1
  2. The next number is 2
  3. The next number is 3
  4. The next number is 4
  5. The next number is 5
  6. The next number is 6
  7. The next number is 7
  8. The next number is 8
  9. The next number is 9
  10. The next number is 10
seq命令

seq 命令用于产生从某个数到另外一个数之间的所有整数列表。 常见用法如下:

  1. seq [选项]... 尾数
  2. seq [选项]... 首数 尾数
  3. seq [选项]... 首数 增量 尾数

【实列4】采用 seq 命令,结合 for 循环,打印 1 到 10 之间的所有整数。

  1. for i in `seq 1 10`
  2. do
  3.     echo "第$i个数是 $i"
  4. done

输出结果如下:

  1. 第1个数是 1
  2. 第2个数是 2
  3. 第3个数是 3
  4. 第4个数是 4
  5. 第5个数是 5
  6. 第6个数是 6
  7. 第7个数是 7
  8. 第8个数是 8
  9. 第9个数是 9
  10. 第10个数是 10

编程要求

在右侧编辑器 Begin-End 区间补充代码,使用 for 循环和 seq 命令打印 1 到 10 之间的奇数。

任务描述

本关任务:掌握 while 命令的使用方法。

相关知识

三种运算符号
  • 双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令,具体用法请见图 1;
  • []是 Shell 内置关键字,它和 test 命令类似,可用于判断某个条件是否为真。可用于字符串、数值和文件的测试;
  • [[ ]]是 Shell 内置关键字,它和 test 命令类似,也用来检测某个条件是否成立。相比[][[]]功能更强大,支持正则表达式和逻辑运算。
while循环语法

while 循环是 Shell 脚本中最简单的一种循环,当条件满足时,while 重复地执行一组语句;当条件不满足时,就退出 while 循环。

while 循环的用法如下:

  1. while condition   # 此处 condition 可以是(())、[]、[[]]判断结果
  2. do
  3.     statements
  4. 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 文件中追加系统负载情况。

  1. #!/bin/bash
  2. while [ 1 ]   # [ 1 ]和 true 一样,只是前面2边需要有空格
  3. do
  4.         uptime >>/tmp/uptime.log  # >>是重定向符号
  5.         sleep 2
  6. done
  7. #注:
  8. #uptime 用于查看系统负载
  9. #sleep 2 表示程序睡眠一秒

【实例2】计算 1+2...100 的和。

  1. 方式一:
  2. #!/bin/sh
  3. SUM=0
  4. I=1
  5. while [ $I -le 100 ]  #[]中需要变量取值符号"$",而且大于小于只能用"-le"
  6. do
  7.         ((SUM+=I))
  8.         let I++
  9. done
  10. echo $SUM
  11. -------------------------------------------------------------------------------------------------
  12. 方式二:
  13. #!/bin/sh
  14. SUM=0
  15. I=1
  16. while ((I<=100)) #(())中可以不要变量取值符号,大于小于是可以直接用
  17. do
  18.         ((SUM+=I))
  19.         ((I++))
  20. done
  21. echo $SUM
  22. -------------------------------------------------------------------------------------------------
  23. 方式三:
  24. #!/bin/sh
  25. SUM=0
  26. I=100
  27. ((SUM=I*(I+1)/2))
  28. echo $SUM
循环中断和不中断

有些程序执行时,用户希望程序一直运行。在运行【实列1】中脚本时候,我们可以使用 sh shell.sh & 来代替 sh shell.sh 让其一直在后台执行。当我们遇到脚本死循环的时候,也可以使用 Ctrl+z 的方式强制中断。 常用的中断和不中断技巧如下:

  1. 使用"sh shell.sh &"命令 ,即使用 & 在后台运行
  2. 使用"nohup shell.sh &"命令,即使用 nohup 加 & 在后台运行脚本
  3. 利用 screen 保持会话,然后再执行脚本,即使用 screen 保持当前会话
  4. 后台运行的知识:
  5. sh shell.sh &        脚本 shell.sh 放在后台执行
  6. Ctrl+c           停止执行当前脚本或任务
  7. Ctrl+z           暂停执行当前脚本
  8. jobs             查看当前执行的脚本或任务
  9. bg           将当前脚本或任务放到后台执行
  10. kill             关闭当前脚本任务,即以"kill %号码"的形式关闭进程,任务号通过 jobs 获得
  11. fg           将当前的脚本或任务放到前台执行,若有多任务,则"fg 号码"调出相应的任务编号

【实例3】实际操作效果如下:

  1. [centos@mycentos shell]$ sh 2.sh &  #后台运行
  2. [1] 2988
  3. [centos@mycentos shell]$ jobs       #查看任务数
  4. [1]+  Running                 sh 2.sh &
  5. [centos@mycentos shell]$ kill %1    #关闭进程为1的进程
  6. [centos@mycentos shell]$ jobs      
  7. [1]+  Terminated              sh 2.sh #程序已经被关闭

大家可以根据实例 3 在命令行中自己试验一下。

任务描述

本关任务:掌握 until 循环语句的使用。

相关知识

until语句语法

unti 循环和 while 循环恰好相反;当判断条件不成立时才进行循环,一旦判断条件成立,就终止循环。语法如下:

  1. until condition
  2. do
  3.     statements
  4. done

跟 while 一样,condition 表示判断条件,statements 表示要执行的语句(可以只有一条,也可以有多条),do 和 done 都是 Shell 中的关键字。

until 循环的执行流程为:

  • 先对 condition 进行判断,如果该条件不成立,就进入循环,执行 until 循环体中的语句(do 和 done 之间的语句),这样就完成了一次循环;
  • 每一次执行到 done 的时候,都会重新判断 condition 是否成立。如果不成立,就进入下一次循环,继续执行循环体中的语句;如果成立,就结束整个 until 循环,执行 done 后面的其它 Shell 代码;
  • 如果一开始 condition 就成立,那么程序就不会进入循环体,do 和 done 之间的语句就没有执行的机会。

注意:在 until 循环体中必须有相应的语句使得 condition 越来越趋近于“成立”,只有这样才能最终退出循环,否则 until 就成了死循环,会一直执行下去,永无休止。

【实例1】

  1. #!/bin/bash
  2. i=0
  3. until [[ "$i" -gt 5 ]]    #大于5
  4. do
  5.     let "square=i*i"       
  6.     echo "$i * $i = $square"
  7.     let "i++"
  8. done

执行流程:直到 i 大于 5 的时候,循环退出;当变量 i 小于等于 5 的时候,执行 do 和 done 代码块中的命令,这里的 let 是 shell 的内置计算命令。 输入出结果如下:

  1. [root@work02 opt]# bash a.sh
  2. 0 * 0 = 0
  3. 1 * 1 = 1
  4. 2 * 2 = 4
  5. 3 * 3 = 9
  6. 4 * 4 = 16
  7. 5 * 5 = 25

任务描述

本关任务:掌握 shell 语句中的循环嵌套的方法和使用场景,输出系统中的可执行文件。

相关知识

循环语句可以在循环内使用任意类型的命令,包括其他循环命令。这种循环叫作嵌套循环(nested loop)。注意,在使用嵌套循环时,你是在迭代中使用迭代,与命令运行的次数是乘积关系。不注意这点的话,有可能会在脚本中造成问题。

for-for循环嵌套

这里有个在 for 循环中嵌套 for 循环的简单例子。

【实例1】

  1. #!/bin/bash
  2. # nesting for loops
  3. for (( a = 1; a <= 3; a++ ))
  4. do
  5.  echo "Starting loop $a:"
  6.  for (( b = 1; b <= 3; b++ ))
  7.  do
  8.  echo " Inside loop: $b"
  9.  done
  10. done

执行脚本输出结果为:

  1. Starting loop 1:
  2.  Inside loop: 1
  3.  Inside loop: 2
  4.  Inside loop: 3
  5. Starting loop 2:
  6.  Inside loop: 1
  7.  Inside loop: 2
  8.  Inside loop: 3
  9. Starting loop 3:
  10. Inside loop: 1
  11. Inside loop: 2
  12. Inside loop: 3

这个被嵌套的循环(也称为内部循环,inner loop)会在外部循环的每次迭代中遍历一次它所有的值。注意,两个循环的 do 和 done 命令没有任何差别。bash shell 知道当第一个 done 命令执行时,是指内部循环而非外部循环。

for-while循环嵌套

在混用循环命令时也一样,比如在 while 循环内部放置一个 for 循环。

【实例2】

  1. #!/bin/bash
  2. # placing a for loop inside a while loop
  3. var1=5
  4. while [ $var1 -ge 0 ]
  5. do
  6.  echo "Outer loop: $var1"
  7.  for (( var2 = 1; $var2 < 3; var2++ ))
  8.      do   
  9.          var3=$[ $var1 * $var2 ]
  10.          echo " Inner loop: $var1 * $var2 = $var3"
  11.      done
  12. var1=$[ $var1 - 1 ]
  13. done

执行脚本输出结果为:

  1. Outer loop: 5
  2.  Inner loop: 5 * 1 = 5
  3.  Inner loop: 5 * 2 = 10
  4. Outer loop: 4
  5.  Inner loop: 4 * 1 = 4
  6.  Inner loop: 4 * 2 = 8
  7. Outer loop: 3
  8.  Inner loop: 3 * 1 = 3
  9.  Inner loop: 3 * 2 = 6
  10. Outer loop: 2
  11. Inner loop: 2 * 1 = 2
  12. Inner loop: 2 * 2 = 4
  13. Outer loop: 1
  14. Inner loop: 1 * 1 = 1
  15. Inner loop: 1 * 2 = 2
  16. Outer loop: 0
  17. Inner loop: 0 * 1 = 0
  18. Inner loop: 0 * 2 = 0
until-while循环嵌套

如果真的想挑战脑力,可以混用 until 和 while 循环。 【实列3】

  1. #!/bin/bash
  2. # using until and while loops
  3. var1=3
  4. until [ $var1 -eq 0 ]
  5. do
  6.      echo "Outer loop: $var1"
  7.      var2=1
  8.      while [ $var2 -lt 5 ]
  9.          do
  10.              var3=$(echo "scale=4; $var1 / $var2" | bc)
  11.              echo " Inner loop: $var1 / $var2 = $var3"
  12.              var2=$[ $var2 + 1 ]
  13.          done
  14.      var1=$[ $var1 - 1 ]
  15. done

执行脚本输出结果为:

  1. Outer loop: 3
  2.  Inner loop: 3 / 1 = 3.0000
  3.  Inner loop: 3 / 2 = 1.5000
  4.  Inner loop: 3 / 3 = 1.0000
  5.  Inner loop: 3 / 4 = .7500
  6. Outer loop: 2
  7.  Inner loop: 2 / 1 = 2.0000
  8.  Inner loop: 2 / 2 = 1.0000
  9.  Inner loop: 2 / 3 = .6666
  10. Inner loop: 2 / 4 = .5000
  11. Outer loop: 1
  12. Inner loop: 1 / 1 = 1.0000
  13. Inner loop: 1 / 2 = .5000
  14. Inner loop: 1 / 3 = .3333
  15. Inner loop: 1 / 4 = .2500

外部的 until 循环以值 3 开始,并继续执行到值等于 0。内部 while 循环以值 1 开始并一直执行,只要值小于 5。每个循环都必须改变在测试条件中用到的值,否则循环就会无止尽进行下去。

控制循环

你可能会想,一旦启动了循环,就必须苦等到循环完成所有的迭代,并不是这样的。有两个命令能帮我们控制循环内部的情况: break 命令和 continue 命令,每个命令在如何控制循环的执行方面有不同的用法。下面将介绍如何使用这些命令来控制循环。

  • break 命令:跳出单个循环在 shell 执行 break 命令时,它会尝试跳出当前正在执行的循环,请见【实例4】。

【实列4】

  1. #!/bin/bash
  2. # breaking out of a for loop
  3. for var1 in 1 2 3 4 5 6 7 8 9 10
  4. do
  5.      if [ $var1 -eq 5 ];then
  6.          break
  7.      fi
  8.     echo "Iteration number: $var1"
  9. done
  10. echo "The for loop is completed"

执行脚本输出结果为:

  1. Iteration number: 1
  2. Iteration number: 2
  3. Iteration number: 3
  4. Iteration number: 4
  5. The for loop is completed

for 循环通常都会遍历列表中指定的所有值。但当满足 if-then 的条件时,shell 会执行 break 命令,停止 for 循环。

  • continue 命令:continue 命令可以提前中止某次循环中的命令,但并不会完全终止整个循环。可以在循环内部设置 shell 不执行命令的条件。这里有个在 for 循环中使用 continue 命令的简单例子。

【实例5】

  1. #!/bin/bash
  2. # using the continue command
  3. for (( var1 = 1; var1 < 15; var1++ ))
  4. do
  5.      if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
  6.          then
  7.          continue
  8.      fi
  9.      echo "Iteration number: $var1"
  10. done

执行脚本输出结果为:

  1. Iteration number: 1
  2. Iteration number: 2
  3. Iteration number: 3
  4. Iteration number: 4
  5. Iteration number: 5
  6. Iteration number: 10
  7. Iteration number: 11
  8. Iteration number: 12
  9. Iteration number: 13
  10. 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个学生,分别是张三,李四,王五,赵六,如果每一行都按“学生:...”之类的样式输出,则可以如此撰写程序:

  1. #!/bin/bash
  2. for stud in 张三 李四 王五 赵六
  3. do
  4.      echo "学生:$stud“
  5. done
案例演示2
  1. #!/bin/bash
  2. read -p "请输入一个数字,程序将计算从1到这个数字间所有数字的和:" num
  3. s=0
  4. for ((i=1;i<=$num;i=i+1))
  5. do
  6.     s=$(($s+$i))
  7. done
  8. 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个学生,分别是张三,李四,王五,赵六,如果每一行都按“学生:...”之类的样式输出,则可以如此撰写程序:

  1. #!/bin/bash
  2. for stud in 张三 李四 王五 赵六
  3. do
  4.      echo "学生:$stud“
  5. done
案例演示2
  1. #!/bin/bash
  2. read -p "请输入一个数字,程序将计算从1到这个数字间所有数字的和:" num
  3. s=0
  4. for ((i=1;i<=$num;i=i+1))
  5. do
  6.     s=$(($s+$i))
  7. done
  8. 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
  1. #!/bin/bash
  2. s=0
  3. i=0
  4. while [ "$i" != "100" ]
  5. do
  6.     i=$(($i+1))
  7.     s=$(($s+$i))
  8. done
  9. echo "1到100的所有数字的和是:$s"

编程要求

根据要求,在右侧编辑器补充代码,利用while语句实现输出数字1到10。

测试说明

平台会对你编写的代码进行测试:

预期输出: 1 2 3 4 5 6 7 8 9 10

任务描述

本关任务:利用until语句来实现输出数字1到10。

相关知识

为了完成本关任务,你需要掌握:until语句的基本格式。

案例演示1
  1. #!/bin/bash
  2. s=0
  3. i=0
  4. until [ "$i" = "100" ]
  5. do
  6.     i=$(($i+1))
  7.     s=$(($s+$i))
  8. done
  9. echo "1到100的所有数字的和是:$s"

编程要求

根据要求,在右侧编辑器补充代码,利用until语句实现输出数字1到10。

测试说明

平台会对你编写的代码进行测试:

预期输出: 1 2 3 4 5 6 7 8 9 10

猜你喜欢

转载自blog.csdn.net/qq_64314976/article/details/131413163
今日推荐