while 循环和 until 循环的应用实践

文章目录

    • while 循环和 until 循环的应用实践
      • 当型和直到型循环:两种 "重复" 的逻辑
        • while 循环:满足条件就继续
        • until 循环:不满足条件就继续
      • 基础示例:从简单场景学用法
        • 示例 1:竖向打印数字 54321
        • 示例 2:模拟 "赚钱直到目标金额"
        • 示例 3:计算 1 到 100 的总和
        • 示例 4:计算 5 的阶乘(5! = 5×4×3×2×1)
        • 示例 5:猴子吃桃问题(逆向推导)
        • 示例 6:猜数字游戏(带次数统计)
        • 示例 7:CPU 满负荷消耗(带进程守护)
        • wait 指令:等待所有后台任务完成
      • 企业实战:循环的实际应用场景
        • 示例 1:定时监控系统负载
        • 示例 2:守护进程监控 sshd 服务
        • 示例 3:网站可用性监控
        • 示例 4:手机短信平台模拟
      • while 循环按行读取文件的 4 种方式
        • 方式 1:用 exec 重定向输入
        • 方式 2:用 cat 管道传递内容
        • 方式 3:在 done 后指定输入文件
        • 方式 4:用 for 循环(指定分隔符为换行)
      • 企业级高级实战:防御类 DDoS 攻击
        • 示例 1:根据 Web 日志封停高频访问 IP
        • 示例 2:根据并发连接数封停恶意 IP
      • 小结

循环语句是编程中用来重复执行指令的工具,就像生活中 “每天早上喝一杯水” 这样的重复行为。在 Shell 脚本里,常见的循环有 while、until、for 和 select,其中 while 和 until 主要用于 “根据条件重复执行” 的场景。本章我们就来详细聊聊这两种循环的用法,从基础语法到实际场景,让你一看就懂、一用就会。

当型和直到型循环:两种 “重复” 的逻辑

while 循环:满足条件就继续

while循环:当满足A条件,就执行B操作。

语法结构

while <条件表达式>  # 判断条件是否成立
do指令...  # 条件成立时执行的内容
done  # 执行完指令后,回到开头重新判断条件

通俗理解:while 循环就像 “只要下雨,就带伞”—— 只要条件(下雨)成立,就重复执行动作(带伞),直到条件不成立(不下雨)为止。

举个生活例子:

# 只要冰箱里有牛奶,就每天喝一杯
while 冰箱里有牛奶
do喝一杯牛奶
done

执行流程

  1. 先判断条件表达式是否成立;
  2. 成立则执行dodone之间的指令;
  3. 执行完后回到开头,再次判断条件;
  4. 直到条件不成立,跳出循环。
until 循环:不满足条件就继续

until循环:直到A条件满足时,B操作就执行。

语法结构

until <条件表达式>  # 判断条件是否成立
do指令...  # 条件不成立时执行的内容
done  # 执行完指令后,回到开头重新判断条件

通俗理解:until 循环就像 “直到雨停,才不带伞”—— 只要条件(雨停)不成立,就重复执行动作(带伞),直到条件成立(雨停)才停止。

举个生活例子:

# 直到冰箱里没有牛奶,才停止喝牛奶
until 冰箱里没有牛奶
do喝一杯牛奶
done

执行流程

  1. 先判断条件表达式是否成立;
  2. 不成立则执行dodone之间的指令;
  3. 执行完后回到开头,再次判断条件;
  4. 直到条件成立,跳出循环。

基础示例:从简单场景学用法

示例 1:竖向打印数字 54321

实验流程

  1. 定义变量i初始值为 5;
  2. 使用循环判断i是否满足条件(while 用i>0,until 用i==0);
  3. 满足条件时打印i,并让i减 1;
  4. 重复步骤 2-3,直到条件不满足,结束循环。

while 实现

#!/bin/bash
i=5  # 初始值设为5
# 当i>0时,进入循环
while ((i>0))
doecho $i  # 打印当前i的值((i--))  # i减1(相当于i = i - 1)
done

运行结果

5
4
3
2
1

until 实现

#!/bin/bash
i=5  # 初始值设为5
# 直到i==0时,停止循环(即i≠0时一直执行)
until ((i==0))
doecho $i  # 打印当前i的值((i--))  # i减1
done

运行结果

5
4
3
2
1
示例 2:模拟 “赚钱直到目标金额”

实验流程

  1. 设定目标金额target=10000000,初始金额money=0
  2. 使用 until 循环判断money是否达到目标;
  3. 未达到时,打印 “正在赚钱”,每次增加 1000000,休眠 1 秒;
  4. 达到目标后,打印 “hahaha” 并结束。
#!/bin/bash
target=10000000  # 目标金额:1000万
money=0  # 初始金额:0# 直到money >= target时停止循环(未达标时一直执行)
until (($money>=$target))
doecho "I'm working hard to get money..."  # 提示正在赚钱sleep 1  # 休眠1秒(模拟耗时过程)money=$[ money + 1000000 ]  # 每次赚100万echo "I have $money."  # 打印当前金额
done
echo hahaha  # 达标后打印

运行结果

I'm working hard to get money...
I have 1000000.
I'm working hard to get money...
I have 2000000.
...(中间省略)...
I'm working hard to get money...
I have 10000000.
hahaha
示例 3:计算 1 到 100 的总和

实验流程

  1. 定义变量i=1(起始数字)、sum=0(总和);
  2. 使用 while 循环判断i是否小于等于 100;
  3. 满足条件时,将i加到sum中,i加 1;
  4. 循环结束后,打印总和。
#!/bin/bash
i=1  # 从1开始
sum=0  # 初始总和为0# 当i<=100时,持续累加
while ((i<=100))
do((sum+=i))  # 等价于 sum = sum + i((i++))  # i加1(等价于i = i + 1)
done
echo "1+2+3+...+99+100=$sum"  # 打印结果

运行结果

1+2+3+...+99+100=5050
示例 4:计算 5 的阶乘(5! = 5×4×3×2×1)

实验流程

  1. 定义变量i=1(起始乘数)、sum=1(阶乘结果,初始为 1);
  2. 使用 while 循环判断i是否小于等于 5;
  3. 满足条件时,将sum乘以ii加 1;
  4. 循环结束后,打印结果。
#!/bin/bash
i=1  # 从1开始乘
sum=1  # 初始值为1(乘法的"单位元")# 当i<=5时,持续相乘
while ((i<=5))
do((sum*=i))  # 等价于 sum = sum * i((i++))  # i加1
done
echo "5的阶乘为:$sum"  # 打印结果

运行结果

5的阶乘为:120
示例 5:猴子吃桃问题(逆向推导)

问题描述:猴子每天吃剩下桃子的一半加 1 个,第 10 天早上只剩 1 个桃。求第一天摘了多少桃?

实验流程

  1. 已知第 10 天早上有 1 个桃,逆向推导前一天的数量(前一天 = (当天 + 1) × 2);
  2. 从第 10 天推到第 1 天,需要循环 9 次;
  3. 定义变量today=1(第 10 天的桃),循环计算前一天的数量并更新today
  4. 循环结束后,today即为第一天的数量。

while 循环实现

#!/bin/bash
today=1  # 第10天早上的桃子数量
lastday=0  # 用于存储前一天的数量
i=1  # 循环计数器# 循环9次(从第10天推到第1天)
while ((i<=9))
dolastday=$[(today+1)*2]  # 计算前一天的数量:前一天 = (当天 + 1) × 2today=${lastday}  # 更新today为前一天的数量(向前推一天)((i++))  # 计数器加1
done
echo "猴子第一天摘的桃子数量是:$today。"

运行结果

猴子第一天摘的桃子数量是:1534。

函数递归实现

#!/bin/bash
# 定义递归函数:计算第n天早上的桃子数量
function sum (){if [[ $1 = 10 ]];then  # 第10天早上固定是1个echo 1else# 前一天 = (当天 + 1) × 2(递归调用下一天的结果)echo $[ ($(sum $[$1 +1]) + 1)*2 ]fi
}
echo "猴子第一天摘的桃子数量是:$(sum 1)。"  # 计算第1天的数量

运行结果

猴子第一天摘的桃子数量是:1534。
示例 6:猜数字游戏(带次数统计)

实验流程

  1. 系统生成 1-50 的随机数,保存到临时文件;
  2. 提示用户猜数字,记录猜测次数;
  3. 若猜测正确,提示次数并清理临时文件;
  4. 若猜错,提示 “太大” 或 “太小”,继续猜测;
  5. 若输入超出 1-50,提示重新输入。
#!/bin/bash
# 生成1-50的随机数(RANDOM是系统随机数,%50取0-49,+1后为1-50)
random_num=$[ RANDOM%50+1 ]
echo "${random_num}" >> /tmp/number  # 保存到临时文件(可用于验证)i=0  # 猜测次数计数器# 无限循环(直到猜对才退出)
while true
doread -p "猜一猜系统产生的50以内随机数是:" num  # 读取用户输入# 判断输入是否在1-50之间if ((num>=1 && num<=50));then((i++))  # 次数加1# 判断是否猜对if [ $num -eq ${random_num} ];thenecho "恭喜你,第$i次猜对了!"rm -f /tmp/number  # 清理临时文件exit  # 退出脚本elseecho -n "第$i次猜测,加油。"# 提示猜大或猜小[ $num -gt ${random_num} ] && echo "太大了,往小猜。" || echo "太小了,往大猜。"fielseecho "请输入一个介于1-50之间的数字。"  # 输入无效时提示fi 
done

运行示例

猜一猜系统产生的50以内随机数是:25
第1次猜测,加油。太大了,往小猜。
猜一猜系统产生的50以内随机数是:10
第2次猜测,加油。太小了,往大猜。
猜一猜系统产生的50以内随机数是:15
恭喜你,第3次猜对了!
示例 7:CPU 满负荷消耗(带进程守护)

实验流程

  1. 获取 CPU 核心数,启动对应数量的 “CPU 负载进程”(无限循环计算 1+1);
  2. 持续监控进程数量,若少于 CPU 核心数,自动补充新进程;
  3. 即使管理员杀死进程,也会重新启动,直到手动终止脚本。

cpu_load 脚本(负载进程)

#!/bin/bash
# 无限循环执行1+1(消耗CPU资源)
while true;do let 1+1;done

multi_cpu_load 脚本(进程守护)

#!/bin/bash
# 获取CPU核心数(通过lscpu命令过滤)
cpu_count=$(lscpu|egrep '^CPU\(s' | awk '{print $2}')\# 启动与CPU核心数相同的负载进程
for ((i=1;i<=cpu_count;i++))
dobash /root/bin/cpu_load &  \# 后台运行负载进程
done\# 持续监控进程数量,不足则补充
while true
do\# 统计当前负载进程数量(排除grep自身)current_count=$(ps axu |grep cpu_load |grep -v grep| wc -l)\# 若数量少于CPU核心数,补充新进程if [ $current_count -lt ${cpu_count} ];thenbash /root/bin/cpu_load &sleep 3  \# 间隔3秒再检查fi 
done
```**验证方法**:
1. 运行脚本:`bash multi_cpu_load &`2. 查看CPU使用率:`top`(按`1`显示每个核心,可见所有核心使用率接近100%);
3. 手动杀死一个负载进程:`pkill -f cpu_load`4. 再次查看进程:`ps aux | grep cpu_load`(会发现进程数量自动恢复)。\##\# 10.3 脚本后台运行:防止执行中断在实际工作中,脚本可能需要长时间运行(如监控脚本),若不小心关闭终端或按`Ctrl+C`,脚本就会中断。以下是几种防止中断的方法:| 方法 | 命令示例 | 说明 |
|------|----------|------|
| 后台运行 | `sh script.sh &` | 脚本在后台运行,终端关闭后会停止 |
| 忽略挂断信号 | `nohup sh script.sh &` | 终端关闭后仍继续运行,输出保存到`nohup.out` |
| 保持会话 | `screen -S session1` <br> 然后执行脚本 | 关闭终端后,可通过`screen -r session1`恢复会话 |**常用操作命令**:
- `Ctrl+C`:停止当前前台运行的脚本;
- `Ctrl+Z`:暂停当前前台脚本,放入后台(状态为`Stopped`);
- `bg %任务编号`:将暂停的后台任务转为运行状态(如`bg %1`);
- `fg %任务编号`:将后台任务调回前台(如`fg %1`);
- `jobs`:查看当前后台任务列表(含编号);
- `kill %任务编号`:终止后台任务(如`kill %1`)。\##\## 示例:让所有CPU满负荷工作(简化版)
```bash
\#!/bin/bash
\# 获取CPU核心数
cpu_count=$(lscpu|grep '^CPU(s)'|awk '{print $2}')
i=1\# 为每个CPU核心启动一个负载进程
while ((i<=${cpu_count}))
do{  \# 将命令组放入后台运行while :  \# 等价于while true(无限循环)do((1+1))  \# 简单计算消耗CPUdone} &  \# 后台运行该命令组((i++))  \# 计数器加1
done
```
**验证**:运行后用`top`命令查看,所有CPU核心使用率接近100%。\##\# 10.4 并发控制:限制同时运行的进程数当需要批量执行任务时,若进程过多会占用大量资源,因此需要控制并发数量(如不超过CPU核心数)。\##\## 示例:控制并发数不超过CPU核心数
**cpu_load 脚本(限时负载)**:
```bash
\#!/bin/bash
\# 后台运行负载进程
while true
do((1+1))
done &pid=$!  \# 获取后台进程的PID
sleep 10 && kill -9 $pid  \# 10秒后自动杀死该进程
```**multi_cpu_load 脚本(并发控制)**:
```bash
\#!/bin/bash
\# 获取CPU核心数
cpu_count=$(lscpu | awk '/^CPU\(s\):/ { print $2}')# 无限循环启动负载进程
while true
dobash /home/bq/cpu_load &  # 启动一个负载进程# 检查当前并发数,若超过CPU核心数则等待while truedojobs=$(jobs -l |wc -l)  # 统计当前后台任务数if [ $jobs -ge $cpu_count ];thensleep 3  # 并发数已满,休眠3秒再检查elsebreak  # 并发数未满,退出内层循环,继续启动新进程fidone
done

验证:运行后用jobs命令查看,后台任务数始终等于 CPU 核心数。

wait 指令:等待所有后台任务完成
#!/bin/bash
> /tmp/sleep  # 清空临时文件(用于记录结果)
i=1# 启动10个后台任务(分别休眠1-10秒)
while [ $i -le 10 ]
do# 休眠i秒后,将结果写入文件(&表示后台运行)( sleep $i && echo sleep $i >> /tmp/sleep )&((i++))
donewait  # 等待所有后台任务完成
cat /tmp/sleep  # 打印所有结果(按休眠时间排序)

运行结果

sleep 1
sleep 2
sleep 3
sleep 4
sleep 5
sleep 6
sleep 7
sleep 8
sleep 9
sleep 10

企业实战:循环的实际应用场景

示例 1:定时监控系统负载

实验流程

  1. 无限循环执行uptime命令(查看系统负载);
  2. 每次执行后休眠 2 秒;
  3. 可选:将结果写入日志文件(后台运行时用)。
#!/bin/bash
# 无限循环监控系统负载
while true
douptime  # 输出系统负载信息(当前时间、运行时间、用户数、平均负载)sleep 2  # 每2秒监控一次
done

运行结果

 10:23:45 up 2 days,  3:15,  2 users,  load average: 0.05, 0.03, 0.0010:23:47 up 2 days,  3:15,  2 users,  load average: 0.05, 0.03, 0.00
...(每2秒输出一次)

后台日志版

#!/bin/bash
while true
douptime >> /tmp/loadaverage.log  # 结果写入日志sleep 2
done

使用方法bash while2.sh &(后台运行),用tail -f /tmp/loadaverage.log查看实时日志。

示例 2:守护进程监控 sshd 服务

实验流程

  1. 无限循环检查 sshd 服务状态;
  2. 若服务未运行,自动重启;
  3. 每 5 秒检查一次。

while 实现

#!/bin/bash
while true
do # 检查sshd服务是否活跃(&>/dev/null表示不输出结果)systemctl is-active sshd.service &>/dev/nullif [ $? -ne 0 ];then  # $?为0表示服务正常,非0表示异常systemctl restart sshd.service  &>/dev/null  # 重启服务echo "sshd restarted at $(date)" >> /tmp/sshd_monitor.log  # 记录重启时间fisleep 5  # 每5秒检查一次
done

until 实现

#!/bin/bash
# until false 等价于while true(因为false永远不成立,所以循环无限执行)
until false
do systemctl is-active sshd.service &>/dev/nullif [ $? -ne 0 ];then systemctl restart sshd.service  &>/dev/nullecho "sshd restarted at $(date)" >> /tmp/sshd_monitor.logfisleep 5
done

验证:手动停止 sshd 服务(systemctl stop sshd),5 秒后查看状态(systemctl status sshd),会发现服务已自动重启。

示例 3:网站可用性监控

实验流程

  1. 接收用户输入的 URL 作为参数;
  2. 无限循环用curl检查 URL 是否可访问;
  3. 每 3 秒检查一次,输出 “正常” 或 “异常”。
#!/bin/bash
# 检查参数:必须提供一个URL
if [ $# -ne 1 ];thenecho "Usage: $0 url"  # 提示用法(如:bash check_url.sh www.baidu.com)exit 1
fiurl="$1"  # 保存URL参数while true
do# curl选项:-o /dev/null(不保存输出)、-s(静默模式)、--connect-timeout 5(超时5秒)if curl -o /dev/null -s --connect-timeout 5 $url;thenecho "$url is ok."  # 访问成功elseecho "$url is error."  # 访问失败fisleep 3  # 每3秒检查一次
done

运行示例

bash check_url.sh www.baidu.com
www.baidu.com is ok.
www.baidu.com is ok.
...
示例 4:手机短信平台模拟

实验流程

  1. 初始余额 0.5 元,每条短信花费 0.15 元;
  2. 提供菜单:查询余额、发送短信、充值、退出;
  3. 发送短信前检查余额,不足则提示充值;
  4. 充值时验证输入为正数,否则提示重新输入。
#!/bin/bashmoney=0.5  # 初始余额(单位:元)
msg_file=/tmp/message  # 保存短信的文件
> $msg_file  # 清空文件# 打印菜单函数
function print_menu () {cat << EOF
1. 查询余额
2. 发送消息
3. 充值
4. 退出
EOF
}# 检查输入是否为数字
function check_digit () {# expr计算失败时返回非0,用于判断是否为数字expr $1 + 1 &> /dev/null && return 0 || return 1
}# 显示当前余额
function check_money_all () {echo "余额为:$money 元。"
}# 检查余额是否足够发送一条短信(0.15元)
function check_money () {# 将余额转换为分(避免小数计算误差)new_money=$(echo "$money*100"|bc|cut -d . -f1)if [ ${new_money} -lt 15 ];then  # 小于15分(0.15元)echo "余额不足,请充值。"return 1  # 余额不足返回1elsereturn 0  # 余额充足返回0fi
}# 充值函数
function chongzhi () {read -p "充值金额(单位:元):" chongzhi_moneywhile truedocheck_digit $chongzhi_money  # 检查是否为数字# 若为数字且>=1元,则执行充值if [ $? -eq 0 ] && [ ${chongzhi_money} -ge 1 ];then# 用bc工具处理小数加法money=$( echo "($money+${chongzhi_money})"|bc)echo "充值成功,当前余额为:$money 元"return 0elseread -p "输入无效,请重新输入充值金额(至少1元):" chongzhi_money fidone
}# 发送短信函数
function send_msg () {check_money  # 检查余额if [ $? -eq 0 ];then  # 余额充足read -p "请输入短信内容:" messageecho "$message" >> ${msg_file}  # 保存短信# 计算扣除0.15元后的余额(转换为分计算)new_money=$(echo "scale=2;($money*100-15)" | bc |cut -d. -f1 )# 转换回元(处理小于1元的情况,如0.35元)if [ ${new_money} -ge 100 ];thenmoney=$(echo "scale=2;${new_money}/100" | bc )elsemoney=0$(echo "scale=2;${new_money}/100" | bc )fiecho "发送成功,当前余额为:$money 元"fi
}# 主程序(无限循环显示菜单)
while true
doprint_menuechoread -p "请输入你的选择(1-4):" choiceclear  # 清屏,使界面整洁case  $choice in1)check_money_all  # 调用查询余额函数;;2)send_msg  # 调用发送短信函数;;3)chongzhi  # 调用充值函数;;4)exit  # 退出脚本;;*)echo "输入错误,请从1、2、3、4中选择。" ;;esacecho
done

运行示例

1. 查询余额
2. 发送消息
3. 充值
4. 退出请输入你的选择(1-4):1
余额为:0.5 元。1. 查询余额
2. 发送消息
3. 充值
4. 退出请输入你的选择(1-4):2
请输入短信内容:hello
发送成功,当前余额为:0.35 元

while 循环按行读取文件的 4 种方式

读取文件内容是脚本中常见的操作,以下是用 while 循环按行读取/etc/hosts文件的 4 种方法:

方式 1:用 exec 重定向输入
#!/bin/bash
exec < /etc/hosts  # 将文件内容重定向为标准输入
# 循环读取每一行(read line会自动读取下一行,直到文件结束)
while read line
doecho $line  # 打印当前行
done
方式 2:用 cat 管道传递内容
#!/bin/bash
# cat读取文件内容,通过管道传给while循环
cat /etc/hosts | while read line
doecho $line
done
方式 3:在 done 后指定输入文件
#!/bin/bash
# 循环读取行,done后指定输入文件
while read line
doecho $line
done < /etc/hosts  # 输入重定向到文件
方式 4:用 for 循环(指定分隔符为换行)
#!/bin/bash
IFS=$'\n'  # 将分隔符设为换行(默认包含空格、制表符等,会拆分一行)
# 遍历文件内容的每一行
for line in $(cat /etc/hosts)
doecho $line
done

说明:方式 1-3 功能相同,方式 4 适合用 for 循环的场景,但需注意文件中是否有特殊字符(如空格)。

企业级高级实战:防御类 DDoS 攻击

示例 1:根据 Web 日志封停高频访问 IP

场景:若某个 IP1 小时内访问次数(PV)超过 500,判定为恶意攻击,用 iptables 封停。

实验流程

  1. 每小时分析一次 Web 日志,提取所有访问 IP;
  2. 统计每个 IP 的访问次数;
  3. 对次数超过 500 且未被封停的 IP,执行封停命令并记录。
#!/bin/bash
logfile=$1  # 接收Web日志文件路径作为参数# 无限循环,每小时执行一次
while true
do# 提取日志中第1列(IP),去重并统计次数,保存到临时文件awk '{print $1}' $logfile | grep -v "^$" | sort |uniq -c > /tmp/tmp.logexec < /tmp/tmp.log  # 读取临时文件内容while read linedoip=$(echo $line |awk '{print $2}')  # 提取IPcount=$(echo $line |awk '{print $1}')  # 提取访问次数# 若次数>500且未被封停,则执行封停if [ $count -gt 500 ] && [ $(iptables -L -n|grep "$ip" |wc -l) -lt 1 ];theniptables -I INPUT -s $ip -j DROP  # 封停IPecho "$(date +'%F %T') $ip is dropped (count=$count)" >> /tmp/droplist_$(date +%F).log  # 记录日志fidonesleep 3600  # 每3600秒(1小时)执行一次
done

使用方法bash block_ip_by_log.sh /var/log/nginx/access.log(需替换为实际日志路径)。

示例 2:根据并发连接数封停恶意 IP

场景:若某个 IP 的并发连接数超过 100,判定为恶意攻击,用 iptables 封停。

实验流程

  1. 每 10 秒统计一次 ESTABLISHED 状态的连接;
  2. 提取客户端 IP 并统计连接数;
  3. 对连接数超过 100 且未被封停的 IP,执行封停命令并记录。
#!/bin/bash
# 无限循环,每10秒执行一次
while true
do# 提取ESTABLISHED状态连接的客户端IP(第4列是客户端地址,:前为IP)ss -t | grep ESTAB|awk '{print $4}' | cut -d: -f1 | sort |uniq -c > /tmp/tmp.logexec < /tmp/tmp.log  # 读取临时文件内容while read linedoip=$(echo $line |awk '{print $2}')  # 提取IPcount=$(echo $line |awk '{print $1}')  # 提取连接数# 若连接数>100且未被封停,则执行封停if [ $count -gt 100 ] && [ $(iptables -L -n|grep "$ip" |wc -l) -lt 1 ];theniptables -I INPUT -s $ip -j DROP  # 封停IPecho "$(date +'%F %T') $ip is dropped (count=$count)" >> /tmp/droplist_$(date +%F).log  # 记录日志fidonesleep 10  # 每10秒执行一次
done

验证:运行脚本后,用ss -t | grep ESTAB | awk '{print $4}' | cut -d: -f1 | sort | uniq -c查看 IP 连接数,模拟高并发后会被自动封停。

小结

  1. while vs until
    • while 是 “条件成立就执行”(当型循环),适合 “满足条件持续做” 的场景(如守护进程);
    • until 是 “条件不成立就执行”(直到型循环),适合 “不满足条件持续做,满足后停止” 的场景。
  2. 常见用法场景
    • 无限循环(while true):用于监控、守护进程(需配合sleep控制频率);
    • 按条件重复:如计数、累加、逆向推导(如猴子吃桃);
    • 读取文件:按行处理文本内容(4 种读取方式);
    • 并发控制:限制后台进程数量,避免资源耗尽。
  3. 实战技巧
    • 后台运行脚本用nohupscreen,防止中断;
    • wait等待所有后台任务完成;
    • 防御攻击时,结合日志 / 连接数统计 + 防火墙命令,实现自动封停。

通过本章学习,你已经掌握了循环的核心逻辑和实际应用,接下来可以尝试用循环解决更多复杂场景(如批量处理文件、定时任务等)。

如涉及版权问题,请联系作者处理!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94332.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94332.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/94332.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chromadb使用hugging face模型时利用镜像网站下载注意事项

chromadb默认使用sentence-transformers/all-MiniLM-L6-v2的词嵌入&#xff08;词向量&#xff09;模型&#xff0c;如果在程序首次运行时&#xff0c;collection的add或query操作时如果没有指定embeddings或query_embeddings&#xff0c;程序会自动下载相关嵌入向量模型&#…

基于大模型的对话式推荐系统技术架构设计

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《GPT多模态大模型与AI Agent智能体》&#xff08;跟我一起学人工智能&#xff09;【陈敬雷编著】【清华大学出版社】 清华《GPT多模态大模型与AI Agent智能体》书籍配套视频课程【陈敬雷…

第1章 React组件开发基础

在掌握React开发之前,我们需要先建立扎实的组件开发基础。这些基础知识不仅影响你的开发效率,更决定了应用程序的性能、可维护性和团队协作的顺畅程度。 本章将深入探讨React组件开发的核心技巧,从JSX语法优化到组件架构设计,帮你建立正确的React开发思维模式。 🗂️ 本…

【yocto】Yocto Project 配置层(.conf)文件语法详解

【加关注&#xff0c;不迷路&#xff0c;持续输出中...】Yocto Project 是一个开源的嵌入式 Linux 系统构建框架&#xff0c;其核心是通过元数据&#xff08;Metadata&#xff09;来定义如何构建系统。这些元数据主要包括配方&#xff08;.bb / .bbappend&#xff09;、配置&am…

知识蒸馏 Knowledge Distillation 序列的联合概率 分解成 基于历史的条件概率的连乘序列

知识蒸馏 Knowledge Distillation 序列的联合概率 分解成 基于历史的条件概率的连乘序列 flyfish 代码实践 论文 Generalized Knowledge Distillation (GKD) On-Policy Distillation of Language Models: Learning from Self-Generated Mistakes 自回归分解 将 “序列的联合…

React15.x版本 子组件调用父组件的方法,从props中拿的,这个方法里面有个setState,结果调用报错

在React 15.x中&#xff0c;子组件通过props调用父组件包含setState的方法时出现错误&#xff0c;最常见的原因是父组件方法的this指向丢失&#xff0c;导致调用setState时出现Cannot read property setState of undefined之类的错误。 核心原因 React类组件的方法默认不会绑定…

交叉编译.so到鸿蒙使用

以下是在 Ubuntu 20.04 系统上的操作&#xff0c;tpc_c_cplusplus 他是把编译的流程都给写进去了&#xff0c;你只需要关注你要编译的库配置好环境就行了。 第一步&#xff1a;下载 tpc_c_cplusplus 仓库地址&#xff1a; GitCode - 全球开发者的开源社区,开源代码托管平台…

LLaMA-Factory 中配置文件或命令行里各个参数的含义

常见参数分类 & 含义对照表&#xff1a; &#x1f539;模型相关参数含义model_name_or_path基础模型的路径&#xff08;本地或 HuggingFace Hub 上的名字&#xff0c;如 meta-llama/Llama-2-7b-hf&#xff09;adapter_name_or_pathLoRA/Adapter 权重路径&#xff08;如果要…

JavaScript 性能优化实战技术文章大纲

一、引言1.1 背景阐述在当今 Web 应用高度交互化、复杂化的趋势下&#xff0c;JavaScript 作为核心脚本语言&#xff0c;其性能优劣直接决定了用户体验的好坏。从单页应用&#xff08;SPA&#xff09;的流畅运行&#xff0c;到复杂数据可视化的实时交互&#xff0c;JavaScript …

正点原子【第四期】Linux之驱动开发学习笔记-2.1LED灯驱动实验(直接操作寄存器)

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子【第四期】手把手教你学Linux系列课程之 Linux驱动开发篇”视频的学习笔记&#xff0c;该课程配套开发板为正点原子alpha/mini Linux开发板。在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内…

【GM3568JHF】FPGA+ARM异构开发板 测试命令

本章节的命令操作均在板卡的终端执行 1 初探/sys目录 与/proc目录类似&#xff0c;/sys目录下的文件/文件夹向用户提供了一些关于设备、内核模块、文件系统以及其他内核组件的信息&#xff0c; 如子目录block中存放了所有的块设备&#xff1b;子目录bus中存放了系统中所有的总…

【Win】Motrix+Aria2浏览器下载加速

系统安装Motrix Motrix官网下载&#xff0c;推荐下载NSIS Installer 安装版 浏览器安装Aria2 下载Aria2插件&#xff0c;然后开发者模式安装到浏览器 Aria2扩展选项的配置如下&#xff1a; 端口号需要改成Motrix的&#xff0c;默认是16800

SpringBoot applicationContext.getBeansOfType获取某一接口所有实现类,应用于策略模式

本文介绍了如何在Springboot项目中通过ApplicationContext获取接口的实现类&#xff0c;并通过枚举策略模式避免if/else&#xff0c;展示了如何使用getBeansOfType获取TrafficModeService的实现&#xff0c;以及如何在实际场景中应用&#xff0c;如查询交通方式费用 1 在实际工…

大模型问题:幻觉分类+原因+各个训练阶段产生幻觉+幻觉的检测和评估基准

1. 什么是幻觉&#xff1f;大模型出现幻觉&#xff0c;简而言之就是“胡说八道”。 用《A Survey on Hallucination in Large Language Models》1文中的话来讲&#xff0c;是指模型生成的内容与现实世界事实或用户输入不一致的现象。 研究人员将大模型的幻觉分为事实性幻觉&…

智慧冷库物联网解决方案——实现降本增效与风险可控的冷库管理新范式

一、冷库管理痛点设备孤岛化&#xff1a;冷库品牌、型号分散&#xff0c;缺乏统一接入标准&#xff0c;数据互通难&#xff0c;依赖人工巡检&#xff0c;故障响应滞后。能耗黑洞&#xff1a;制冷系统能耗占冷库总运营成本的60%以上&#xff0c;传统管理粗放&#xff0c;缺乏动态…

太空生活的八种要素

数代以来&#xff0c;科学家们一直在银河系中搜寻地外行星存在生命的证据。他们试图找到一组特定的环境条件与化学物质&#xff0c;在恰当的时间、恰当的地点交汇融合。 通过研究人类、植物、动物及微生物在地球上的生存与繁衍方式&#xff0c;科学家们已识别出生命演化所需的关…

Flutter 小技巧之有趣的 UI 骨架屏框架 skeletonizer

很久没有更新过小技巧系列&#xff0c;今天简单介绍一个非常好用的骨架屏框架 skeletonizer &#xff0c;它主要是通过将你现有的布局自动简化为简单的骨架&#xff0c;并添加动画效果来实现加载过程&#xff0c;而使用成本则是简单的添加一个 Skeletonizer 作为 parent &…

基于SpringBoot的宠物用品系统【2026最新】

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

MongoDB 分片集群修改管理员密码

记得关注一下博主&#xff0c;博主每天都会更新IT技术&#xff0c;让你有意想不到的小收获哦^_^ 文章目录*记得关注一下博主&#xff0c;博主每天都会更新IT技术&#xff0c;让你有意想不到的小收获哦^_^*一、注释MongoDB分片集群认证参数&#xff08;三台主机都要操作&#xf…

C++函数重载与引用详解

一、函数重载&#xff1a;同名函数的 “差异化生存”​1. 概念定义​函数重载&#xff08;Function Overloading&#xff09;是 C 的重要特性&#xff0c;指在同一作用域内&#xff0c;允许存在多个同名函数&#xff0c;但要求这些函数的参数列表必须不同。&#xff08;参数个数…