一、循环与遍历机制

1.1 核心概念辨析

遍历(Traversal)定义:指对一组数据结构中每个元素进行一次访问处理的过程,类比点名,即从第一个元素处理到最后一个元素。

循环(Loop)定义:指重复执行一段代码的行为,通常用于处理需要多次执行相同逻辑的场景。

1.2 循环语法与实战演练

基础循环结构:`for` 循环的标准格式为 `for 变量名 in 取值列表; do 执行命令; done`,演示了输出 1 到 5 数字的简单循环。

批量操作应用:利用 `for` 循环读取文件中的 IP 地址列表(`ping.txt`),自动执行 `ping` 命令检测网络连通性,解决了手动逐条执行命令的低效问题。

二、For 循环基础语法与逻辑解析

2.1 循环结构与变量控制

基础语法定义:For 循环由 `for 变量名 in 范围` 构成,其中“范围”决定了循环的次数,若范围包含 5 个元素则循环 5 次,包含 3 个元素则循环 3 次。

for 循环 
for i in 范围区间 
do 
执行逻辑
done 

for ((i=0;i<=5;i++))
do
执行逻辑
done 

变量赋值逻辑:每次循环时,范围中的元素会被依次赋值给指定的变量(如 `I`),并通过 `$I` 在 `do` 后的执行逻辑中进行引用。

2.2 文件读取与循环执行

文件内容遍历:通过 `cat` 命令读取文件内容(如 `ping.txt`),将文件中的每一行作为一个元素进行循环处理。

执行流程演示:演示了脚本读取文件中的 IP 地址(如 110.1, 110.2, 110.100),并依次执行 `ping` 命令,其中 110.100 因无法连通而显示失败。

2.3 For 循环语法结构详解

2.3.1 类 C 语言风格 For 循环格式

标准语法结构:介绍了 `for ((i=0; i<=5; i++))` 的写法,其中双括号 `((...))` 是固定语法,用于数值计算。

循环体定义:`do` 表示开启一次循环任务,`done` 表示单次循环结束,两者之间的语句为循环体。

类C语言的for循环格式
#!/bin/bash
for((i=0;i<=5;i++))       #定义for的条件、循环次数、每次循环后执行的操作
do						  #表示开启一次循环任务
echo "$i"                 #每次循环执行的指令
done                      #一次for 循环结束标志

以上每次循环的工作逻辑:
第一循环:
① 赋值:i=0
② 比较: 0<=5 返回值=0,成立则继续执行循环,不成立则停止并退出循环
③ do ;echo $i --> 会输出 0
④ 进行 i++ (相当于:let i=i+1)自加1的操作并赋值给i,此时i=1
第一次循环结束 

第二次循环
① 赋值:i=1
② 比较: 1<=5 返回值=0,成立则继续执行循环,不成立则停止并退出循环
③ do ;echo $i --> 会输出 1
④ 进行 i++ (相当于:let i=i+1)自加1的操作并赋值给i,此时i=2
第二次循环结束 

2.3.2 循环执行逻辑拆解

四步执行流程:详细拆解了 `for ((i=0; i<=5; i++))` 的执行逻辑,包括变量初始化、条件判断、执行循环体、变量自增四个步骤。

退出条件判定:循环的退出取决于中间的条件判断(如 `i<=5`),当条件不成立时循环停止。

自增运算符:`i++` 等同于 `i=i+1`,表示每次循环结束后变量 i 的值加 1。

变量值变化推演:通过推演 `i` 从 0 到 5 的变化过程,解释了为何循环体输出的是当前值,而自增操作在循环体执行完毕后进行。

次数调整方法:演示了通过修改自增表达式来控制循环次数,如将 `i++` 改为 `i+=2`,使变量每次增加 2。

调整效果:当i++调整为 2 时,循环次数减少,输出结果变为 0, 2, 4。

2.3.3 死循环

for((;;))#死循环 

2.4补充 shell命令进阶技巧

echo 命令的选项与转义符  -n 选项(不换行输出):使用 `echo -n` 可以实现输出内容后不自动换行,适用于需要连续输出的场景。

-e 选项(启用转义):启用 `echo -e` 后,可以在输出内容中解析转义字符,如 `\n` 表示换行,常用于格式化输出或写入文件时的换行控制。

2.5 continue` 与 `break` 的核心区别

`continue` 跳过本次循环:当条件满足时,`continue` 会立即跳过当前循环次数的后续操作,直接进入下一次循环,不影响后续循环的执行。

举例

vim a.sh         #创建脚本a.sh
脚本内容:
#!/bin/bash
for i in {1..5}  #for循环5次从i=1开始到i=5    
do
if [ $i -eq 3 ]  #if判断语句,若$1等于3则执行then的内容
then 
continue         #当$i=3时跳出循环但不影响后面循环  
fi               #结束if语句
echo "$i"        #没执行一次for循环输出一次$i
done             #for循环结束语句
sh a.sh        #调用shell执行脚本
输出结果
1
2
4
5

#可以实现吗?
#!/bin/bash
for i in {1..10}
do
if [ $i -eq 5 ]
then continue 2
fi
echo i=$i
done

再来看一个例子:
for j in {1..3}
do
    for i in {1..5}
    do
        if [ $i -eq 2 ]
        then
        continue 
        fi
    echo "$i"          
    done
done

continue 2 是一个 Shell 中的控制结构,它的作用是在循环内部跳过本次循环并继续下一次循环,
而且会跳过两层循环,即在两层循环内部执行。

在嵌套循环中,如果我们使用 continue 2 命令,
它将跳过包含它的内层循环和外层循环的迭代,并继续执行下一次外层循环的迭代。

`break` 终止整体循环:`break` 不仅会终止当前循环的后续操作,还会直接结束整个循环结构(包括后续所有循环次数),常用于死循环的退出。

break跳出循环
在某个循环中遇到break直接结束此次循环,但是不影响外边嵌套的循环。

break  [数字] 结束数字中的几次循环,若为2则结束自己所在循环和外边嵌套的一层循环,
若为3则结束自己所在循环和外边嵌套的2层循环

脚本内容:
#!/bin/bash 
for j in {1..3}          #第一层for循环,j=1,2,3各执行一次do的内容
do                       #第一层for循环的执行内容
    for i in {1..5}      #第二层for循环,i=1,2,3,4,5各执行一次do的内容
    do                   #第二层for循环的执行内容  
        if [ $i -eq 3 ]  #第二层for循环中添加的if判断语句,当$i=3是执行then内容
        then                
        break 2          #第二层for循环判断语句执行命令,break控制循环的流程
        fi               #if语句结束
    echo "$i"            #第二层for循环语句执行每循环一次输出$i
    done                 #第二层for循环语句结束标志                
done                     #第一层for循环语句结束标志
sh a.sh                #调用bash执行a.sh脚本

具体来说,这段脚本的执行过程如下:
外部循环 for j in {1..3} 循环执行三次,j 分别等于 1、2、3。
在每次外部循环开始时,内部循环 for i in {1..5} 循环执行五次,i 分别等于 1、2、3、4、5。
在内部循环中,当 i 等于 3 时,执行 break 跳出循环。
在内部循环中,使用 echo "$i" 打印当前的数字序列。
在内部循环执行完毕后,外部循环继续执行,直到执行完三次为止
1
2
1
2
1
2

break 命令并不控制循环次数,它是用于控制循环流程的。
当 break 命令执行时,它会立即跳出当前的循环并继续执行循环后面的代码。

多层循环跳过机制:`continue` 和 `break` 后接数字(如 `continue 2`)可控制跳过的循环层数。`continue 2` 表示跳过当前层及外层循环,直接进入外层循环的下一次迭代。

脚本退出指令对比:`exit` 命令会直接结束整个脚本进程,而 `break` 仅影响当前循环结构,不影响后续脚本任务的执行。

三、实战案例

3.1 1 到 100 累加求和

数字累加脚本(1-100) 
需求:编写脚本实现计算从1加到100的值
sum=0
for((i=0;i<=100;i+=2))
do 
let sum=$sum+$i
done 
echo $sum

1. 脚本编写与执行
变量定义与初始化:定义了 `sum` 变量用于存储总和,`i` 变量作为循环计数器。
循环体逻辑:利用 `let` 命令进行累加操作,即 `let sum=$sum+$i`,循环结束后输出结果。
结果验证:执行脚本后输出结果为 5050,验证了脚本逻辑的正确性。
2. 算术运算扩展
运算符号支持:除了基础的加减法,脚本支持乘法(`*`)、除法(`/`)及取余(`%`)运算。
步长控制:演示了通过 `i+=2` 的方式控制循环步长,可用于计算特定间隔的数列和。

3.2 奇偶数的判断与累加逻辑

求从1到100所有整数的偶数和、奇数和 

求从1到100所有整数的偶数和、奇数和 
#!/bin/bash

num1=0                                   #偶数和的初始值
num2=0                                   #奇数和的初始值

for i in {1..100}
do
  if (( i % 2 == 0 )); then              #判断i是否是偶数
    num1=$(($num1+i))                    #如果是偶数,则加到偶数和中
  else
    num2=$(($num2+i))                    #如果是奇数,则加到奇数和中
  fi
done

echo "1 到 100 中所有偶数的和为:$num1"
echo "1 到 100 中所有奇数的和为:$num2"

取余运算判断奇偶:通过 `i%2` 的取余运算结果来判断奇偶数,若余数为 0 则为偶数,否则为奇数。

循环累加实现:在 for 循环内通过 `sum1=$sum1+$i` 的方式进行累加,并强调输出语句应放在循环体外,避免每次循环都输出结果。

需求扩展与优化:演示了将固定区间(1-100)修改为用户输入区间(1-n)的脚本优化方法,并指出直接使用“总和减偶数”的取巧方法在需求变更时不具备通用性。

3.3 九九乘法口诀表的实现逻辑

9*9乘法表
第一步:
vim 99.sh              #创建99.sh脚本
脚本内容:
#!/bin/bash
for i in {1..9}        #for循环9次从i=1开始
do
echo -n "*"            #每循环一次打印一个*,echo  -n参数表示不换行
done                   #此for循环语句结束
bash  99.sh            #调用shell执行脚本
执行结果:
*********

第二步:
vim 99.sh              #编辑99.sh脚本
脚本内容:
#!/bin/bash
for  i  in  {1..9}     #添加打印列循环,循环9次从i=1开始  
do                     #j循环时做do中的内容    
    for j in {1..9}    #第一步for循环内容不变
    do
    echo -n "*"
    done
echo                   #列循环每循环一次进行换行
done                   #列循环for语句结束标志
bash  99.sh            #调用shell执行脚本
执行结果:
*********
*********
*********
*********
*********
*********
*********
*********
*********

第三步:
vim 99.sh                
脚本内容:
#!/bin/bash
for i in {1..9}               #行循环内容不变  
do                         
    for ((j=1; j<=i; j++))    #修改行循环j的取值范围为展开变量j,即当j=1时i取值只有1,所以循环一次。当 
                               j=2时,i取值为1和2,所以i=1和i=2各循环一次,循环2次。以此类推到j=9
    do
    echo -n "*"
    done
echo                   
done                   
bash  99.sh            #调用shell执行脚本
执行结果:
*
**
***
****
*****
******
*******
********
*********

#!/bin/bash

for i in {1..9}
do
    for ((j=1; j<=i; j++))

    do
let sum
    echo -n "$i*$j=$(($i*$j))"
    done
echo
done
~      
算术运算语法:演示了使用 `$(( ))` 双括号进行算术运算的语法,强调该语法主要用于处理整数运算。
变量引用与迭代:通过 `$i` 和 `$g` 变量演示了循环体中的变量引用,并展示了如何通过表达式 `$i * $g` 实现乘法运算。

制表符应用:利用反斜杠 `\t` 在输出中插入制表符(Tab 键),用于在循环体输出时保持列对齐,模拟表格间距。

换行控制:介绍了 `\n` 和 `echo -e` 的使用,用于在输出结束后进行换行,确保每次循环结果独立显示。


基础图形构建:利用外层循环控制行数(1-9),内层循环控制每行星号数量(1-9),构建出完整的 9x9 方块图形。

斜梯形切割逻辑:通过修改内层循环条件(`j<=i`),使每行的星号数量与行号保持一致,从而将方块图形切割为符合乘法表结构的斜梯形。

动态变量替换:在斜梯形的基础上,将内层循环的星号输出替换为 `$j x $i` 的算式,实现乘法表达式的动态生成。

换行控制:利用 `echo` 不加参数实现换行,确保每次外层循环结束后切换到下一行。

空心正方形打印任务

总结

在循环中使用 break 和 continue 命令时,它们分别有以下作用:

break:在循环内部,当执行到 break 命令时,会立即跳出当前的循环,停止循环执行,然后继续执行下一条指令。
可以使用 break 命令来提前终止循环,例如当达到特定条件时或者已经执行了足够的次数。

continue:在循环内部,当执行到 continue 命令时,会跳过本次循环剩余的代码,并继续下一次循环。
可以使用 continue 命令来跳过循环中的某些操作,例如在特定条件下跳过一次循环,或者只执行符合条件的循环。

在嵌套循环中,可以在 break 和 continue 命令后面指定数字参数,来指定跳出或跳过多层循环。
例如,break 2 会跳出当前循环和外层循环的迭代,而continue 2会跳过当前循环和两层外层循环的迭代。

break和continue命令是控制循环流程重要命令。

补充 转义符

常用转义字符

echo -n 表示不换行输出
echo -e 输出转义字符,将转义后的内容输出到屏幕上  echo -ne 
只有加了-e才能执行下面的转义符:
常用的转义字符如下:   
\b 转义后相当于按退格键(backspace),但前提是"\b"后面存在字符;"\b"表示删除前一个字符,"\b\b"表示删除前两个字符。

\c 不换行输出,在"\c"后面不存在字符的情况下,作用相当于 echo -n; 但是当"\c"后面仍然存在字符时,"\c"后面的字符将不会被输出。

\n 换行,被输出的字符从"\n"处开始另起一行。 
 
\f 换行,但是换行后的新行的开头位置连接着上一行的行尾;

\v 与\f相同;

\t 转以后表示插入tab,即横向制表符;

\r 光标移至行首,但不换行,相当于使用"\r"以后的字符覆盖"\r"之前同等长度的字符;但是当"\r"后面不存在任何字符时,"\r"前面的字符不会被覆盖

\\ 表示插入"\"本身;

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐