Shell 脚本编程:while 循环与 until 循环

循环结构简介

循环语句是 Shell 脚本中用于重复执行一条或一组指令的重要工具,直到满足特定条件时停止执行。Shell 脚本中常见的循环语句包括 while、until、for 和 select。本文将重点介绍 while 和 until 两种循环结构,并通过丰富的示例展示其实际应用场景。

while 循环与 until 循环语法解析

while 循环语法

while 循环属于“当型”循环结构,其基本语法格式为:

while <条件表达式>
do指令...
done

执行逻辑

  • 首先判断条件表达式是否成立
  • 如果成立,则执行循环体内的指令
  • 每次执行到 done 时重新判断条件表达式
  • 直到条件不成立时退出循环

until 循环语法

until 循环属于"直到型"循环结构,其基本语法格式为:

until <条件表达式>
do指令...
done

执行逻辑

  • 当条件表达式不成立时执行循环体
  • 直到条件表达式成立时终止循环

基础应用示例

示例1:竖向打印数字

while 实现方式

#!/bin/bash
i=5
while ((i>0))  # 当i大于0时执行循环
doecho $i     # 打印当前i值((i--))     # i自减1
done

until 实现方式

#!/bin/bash
i=5
until ((i==0))  # 直到i等于0时停止循环
doecho $i       # 打印当前i值((i--))       # i自减1
done

示例2:计算1-100的累加和

#!/bin/bash
i=1
sum=0
while ((i<=100))    # 当i小于等于100时执行循环
do((sum+=i))        # 累加i到sum变量# let sum=sum+i   # 另一种累加方式((i++))           # i自增1# let i++         # 另一种自增方式
done
echo "1+2+3+...+99+100=$sum"  # 输出结果

示例3:计算5的阶乘

#!/bin/bash
i=1
sum=1
while ((i<=5))    # 循环5次
do((sum*=i))      # 累乘计算阶乘((i++))         # i自增1
done
echo "5的阶乘为:$sum"  # 输出结果

示例4:猴子吃桃问题

问题描述

  • 猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个
  • 第二天早上又将第一天剩下的桃子吃掉一半,又多吃了一个
  • 以后每天早上都吃了前一天剩下的一半零一个
  • 到第10天早上想再吃时,发现只剩下一个桃子了

问:猴子第一天摘了多少个桃子?

while循环解法

#!/bin/bash
# 当天桃子数量,第10天为1
today=1
# 前一天桃子数量
lastday=0
# 只需要迭代9次(从第10天倒推回第1天)
i=1
while ((i<=9))
do# 计算上一天桃子数量:today = (lastday/2) - 1 → lastday = (today+1)*2lastday=$[(today+1)*2]# 把上一天的数量当作今天的数量,继续向前推算today=${lastday}((i++))
done
echo "猴子第一天摘的桃子数量是:$today。"

函数递归解法

#!/bin/bash
function sum (){if [[ $1 = 1 ]];thenecho $1  # 第10天只剩1个桃子else# 递归计算:第n天的桃子数 = (第n+1天的桃子数 + 1) * 2echo $[ ($(sum $[$1 -1]) + 1)*2 ]fi
}
echo "猴子第一天摘的桃子数量是:$(sum 10)。"

示例5:猜数字游戏

#!/bin/bash
# 生成1-50的随机数字
random_num=$[ RANDOM%50+1 ]
echo "${random_num}" >> /tmp/number  # 保存随机数(用于调试)# 记录猜测次数
i=0
while true  # 无限循环,直到猜对退出
doread -p "猜一猜系统产生的50以内随机数是:" numif ((num>=1 && num<=50));then  # 验证输入有效性((i++))  # 增加猜测次数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

脚本后台运行与管理

后台运行方法

在实际工作中,可能需要让脚本在后台持续运行:

  1. 使用 & 符号sh /server/scripts/while_01.sh &
  2. 使用 nohup 命令nohup /server/scripts/uptime.sh &
  3. 使用 screen 会话screen -S session_name 然后执行脚本

进程管理命令

  • sh whilel.sh &:后台运行脚本
  • ctl+c:停止当前任务
  • ctl+z:暂停当前任务
  • bg:将任务放到后台运行
  • fg:将任务调到前台运行
  • jobs:查看当前任务
  • kill:终止指定任务

并发控制示例

示例:让所有CPU满负荷工作

#!/bin/bash
# 获取CPU核心数量
cpu_count=$(lscpu|grep '^CPU(s)'|awk '{print $2}')
i=1
while ((i<=${cpu_count}))
do{while :  # 无限循环do((1+1))  # 简单计算消耗CPUdone} &  # 放到后台运行((i++))
done

注意事项

  • { command1; command2; ... } & 可以将多个命令放到后台运行
  • {} 内部两侧需要有空格
  • 最后一个命令后需要有分号

使用wait等待后台任务完成

#!/bin/bash
> /tmp/sleep  # 清空文件
i=1
while [ $i -le 10 ]
do# 每个任务睡眠i秒后写入文件( sleep $i && echo sleep $i >> /tmp/sleep )&((i++))
done
wait  # 等待所有后台任务完成
cat /tmp/sleep  # 显示结果

实战应用

示例1:监控系统负载

#!/bin/bash
while true  # 无限循环
douptime    # 显示系统负载sleep 2   # 休眠2秒
done

后台运行并记录日志

#!/bin/bash
while true
douptime >> /tmp/loadaverage.log  # 追加到日志文件sleep 2
done# 后台运行
bash while2.sh &

示例2:服务监控与自动重启

while格式

#!/bin/bash
while true
do # 检查sshd服务是否活跃systemctl is-active sshd.service &>/dev/nullif [ $? -ne 0 ];then  # 如果服务不活跃systemctl restart sshd.service  &>/dev/null  # 重启服务fisleep 5  # 每5秒检查一次
done

until格式

#!/bin/bash
until false  # 一直执行直到false(永远不会发生)
do systemctl is-active sshd.service &>/dev/nullif [ $? -ne 0 ];then systemctl restart sshd.service  &>/dev/nullfisleep 5
done

示例3:网站可用性监控

#!/bin/bash# 参数检查
if [ $# -ne 1 ];thenecho "Usage: $0 url"exit 1
fiurl="$1"while true
do# 使用curl检查网站可用性if curl -o /dev/null -s --connect-timeout 5 $url;thenecho "$(date): $url is ok."  # 添加时间戳elseecho "$(date): $url is error."fisleep 3  # 每3秒检查一次
done

示例4:简易短信平台模拟

#!/bin/bash# 初始化变量
money=0.5  # 默认金额
msg_file=/tmp/message  # 消息保存文件
> $msg_file  # 清空消息文件# 手机操作菜单
function print_menu () {cat << EOF
1. 查询余额
2. 发送消息
3. 充值
4. 退出
EOF
}# 数字检查函数
function check_digit () {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 ];thenecho "余额不足,请充值。"return 1  # 余额不足elsereturn 0  # 余额充足fi
}# 充值函数
function chongzhi () {read -p "充值金额(单位:元):" chongzhi_moneywhile truedocheck_digit $chongzhi_moneyif [ $? -eq 0 ] && [ ${chongzhi_money} -ge 1 ];thenmoney=$( echo "($money+${chongzhi_money})"|bc)  # 使用bc进行浮点计算echo "当前余额为:$money 元"return 0elseread -p "重新输入充值金额(至少1元):" chongzhi_money fidone
}# 发送消息函数
function send_msg () {check_money  # 检查余额if [ $? -eq 0 ];then  # 余额充足read -p "请输入消息内容:" messageecho "$(date): $message" >> ${msg_file}  # 保存消息带时间戳# 计算新余额(每条消息0.15元)new_money=$(echo "scale=2;($money*100-15)" | bc |cut -d. -f1)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 "请输入你的选择:" choiceclearcase $choice in1)check_money_all;;2)send_msg;;3)chongzhi;;4)echo "感谢使用,再见!"exit;;*)echo "无效选择,请从1、2、3、4中选择。" ;;esacecho
done

while循环读取文件的四种方式

以读取 /etc/hosts 文件为例:

方式1:使用exec重定向

#!/bin/bash
exec < /etc/hosts  # 将文件重定向到标准输入
while read line
doecho $line
done

方式2:使用管道

#!/bin/bash
cat /etc/hosts | while read line
doecho $line
done

方式3:使用输入重定向

#!/bin/bash
while read line
doecho $line
done < /etc/hosts

方式4:设置IFS分隔符

#!/bin/bash
IFS=$'\n'  # 设置字段分隔符为换行符
for line in $(cat /etc/hosts)
doecho $line
done

实战案例

案例1:防止DDoS攻击 - Web日志分析

#!/bin/bash
logfile=$1  # 日志文件路径参数while true
do# 提取IP并统计访问次数awk '{print $1}' $logfile | grep -v "^$" | sort | uniq -c > /tmp/tmp.log# 处理统计结果exec < /tmp/tmp.logwhile 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): $ip is dropped (PV: $count)" >> /tmp/droplist_$(date +%F).logfidonesleep 3600  # 每小时检查一次
done

案例2:防止DDoS攻击 - 网络连接数监控

#!/bin/bash
while true
do# 统计ESTABLISHED状态的连接并按IP分组ss -t | grep ESTAB | awk '{print $4}' | cut -d: -f1 | sort | uniq -c > /tmp/tmp.logexec < /tmp/tmp.logwhile read linedoip=$(echo $line | awk '{print $2}')count=$(echo $line | awk '{print $1}')# 如果单个IP连接数超过100且未被封禁if [ $count -gt 100 ] && [ $(iptables -L -n | grep "$ip" | wc -l) -lt 1 ];theniptables -I INPUT -s $ip -j DROPecho "$(date): $ip is dropped (连接数: $count)" >> /tmp/droplist_$(date +%F).logfidonesleep 10  # 每10秒检查一次
done

总结

  1. while循环特点

    • 擅长执行守护进程和持续运行的应用
    • 适合处理频率小于1分钟的循环任务
    • 多数while循环可用for循环或cron定时任务替代
  2. 各语句使用场景

    • 条件表达式:简短条件判断(文件存在、字符串非空等)
    • if语句:不同值数量较少的条件判断
    • for循环:常规循环处理的首选
    • while循环:守护进程、无限循环(需配合sleep控制频率)
    • case语句:服务启动脚本、固定规则字符串处理
    • select语句:菜单打印(较少使用,通常用here文档替代)
  3. 函数的作用

    • 使代码逻辑更加清晰
    • 减少重复代码开发
    • 提高代码可维护性

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

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

相关文章

LLM 中评价指标与训练概要介绍

在【LLM】LLM 中增量解码与模型推理解读一文中对 LLM 常见名词进行了介绍&#xff0c;本文会对 LLM 中评价指标与训练概要进行介绍&#xff0c;本文并未介绍训练实操细节&#xff0c;未来有机会再了解&#xff5e; 一、LLM 如何停止输出 在看 LLM 评价指标前&#xff0c;先看…

Java 20 新特性及具体应用

目录 1. 模式匹配 for switch&#xff08;预览特性&#xff09; 2. 记录模式&#xff08;预览特性&#xff09; 3. 外部函数与内存 API&#xff08;预览特性&#xff09; 4. 矢量 API&#xff08;孵化器特性&#xff09; 5. 作用域值&#xff08;预览特性&#xff09; 6. …

【STM32】CubeMX(十一):FreeRTOS任务挂起与解挂

这篇文章是 STM32 HAL FreeRTOS 下的任务挂起与恢复机制&#xff0c; 结合 CubeMX 图示与代码&#xff0c;构建了一个 FreeRTOS 控制示例。 本篇目标&#xff1a;创建两个任务&#xff1a; 一个控制蓝灯闪烁&#xff08;myTask01&#xff09; 另一个监控按键&#xff08;Start…

图片预加载:提升Web性能的关键

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

大模型压缩三剑客:量化、剪枝与知识蒸馏全解析

在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;LLM&#xff09;如通义千问、GPT 等已成为推动智能应用的核心引擎。然而&#xff0c;这些模型动辄数十亿甚至上千亿参数&#xff0c;带来了高昂的计算成本和部署门槛。如何在不显著牺牲性能的前提下&#xff0c;让大…

Seaborn数据可视化实战:Seaborn基础图表绘制入门

基础图表绘制&#xff1a;Seaborn入门教程 学习目标 通过本课程的学习&#xff0c;你将掌握如何使用Seaborn库绘制基础图表&#xff0c;包括条形图、折线图和散点图。你将了解Seaborn的基本函数和参数设置&#xff0c;以及如何通过调整这些参数来优化图表的视觉效果。 相关知识…

阿里开源通义万相Wan2.2:视频生成技术的革命性突破

在人工智能视频生成领域,阿里云通义实验室于2025年7月重磅开源了新一代视频生成大模型 Wan2.2,其核心亮点包括人体动作生成的极致精度、电影级美学表达以及高效的资源利用效率,标志着视频生成技术迈入了一个全新的阶段。 一、核心功能:三大模型,覆盖全场景视频生成 Wan2.…

说说你对Integer缓存的理解?

大家好&#xff0c;我是锋哥。今天分享关于【说说你对Integer缓存的理解?】面试题。希望对大家有帮助&#xff1b; 说说你对Integer缓存的理解? 超硬核AI学习资料&#xff0c;现在永久免费了&#xff01; Integer 缓存是 Java 中一个优化机制&#xff0c;它主要通过缓存一部…

高速CANFD收发器ASM1042在割草机器人轮毂电机通信系统中的适配性研究

摘要割草机器人轮毂电机的通信系统对其实现自主控制和高效作业至关重要。本文旨在研究国科安芯推出的高速CANFD收发器芯片ASM1042是否能够满足割草机器人轮毂电机通信系统的复杂需求。通过详细分析轮毂电机通信系统的性能要求&#xff0c;以及ASM1042的电气、功能和环境特性&am…

MTK Linux DRM分析(十二)- KMS Panel框架层(drm_panel.c、drm_mipi_dbi.c、drm_mipi_dsi.c)

一、简介 三个代码文件(drm_mipi_dbi.c、drm_panel.c、drm_mipi_dsi.c)的分析。这些文件都是Linux内核DRM(Direct Rendering Manager)子系统的组成部分,主要用于支持显示面板,特别是通过MIPI(Mobile Industry Processor Interface)接口的显示设备。它们提供了显示驱动…

合合信息acge模型获C-MTEB第一,文本向量化迎来新突破

前言&#xff1a; 在当今时代&#xff0c;大型语言模型以其惊人的发展速度和广泛的应用前景&#xff0c;正成为全球科技界的瞩目焦点。这些模型的强大能力&#xff0c;源自于背后默默支撑它们的Embedding技术——一种将语言转化为机器可理解的数值向量的关键技术。随着大型语言…

26.内置构造函数

2.内置构造函数2.1Object2.2Array2.3String2.4number

tauri配置允许执行eval脚本,在打包cocos游戏web/phone移动端的时候一定要配置

解决办法&#xff1a;在tauriconfig中配置"csp": "default-src self asset: unsafe-inline customprotocol://* http://localhost:* ws:localhost:* unsafe-eval ipc: http://ipc.localhost; script-src unsafe-eval self https://www.googletagmanager.com uns…

K 均值聚类算法学习总结

一、聚类算法基础认知 核心概念&#xff1a;聚类属于无监督学习&#xff0c;核心是把 “相似的样本” 自动分到同一组&#xff08;簇&#xff09;&#xff0c;不需要预先标注的标签。主要挑战是怎么定义 “相似性”、评估聚类效果以及确定最好的聚类数量。 距离度量&#xff1a…

基于Spring Cloud Gateway动态路由与灰度发布方案对比与实践指导

基于Spring Cloud Gateway动态路由与灰度发布方案对比与实践指导 一、问题背景介绍 在微服务架构中&#xff0c;API网关负责统一入口、路由分发与权限校验功能。随着业务需求的不断演进&#xff0c;如何灵活地实现路由动态更新、版本灰度发布以及流量打点就成为运维和开发团队的…

MySQL InnoDB Buffer Pool详解:原理、配置与性能优化

1. 为什么需要 Buffer Pool&#xff1f;1.1 数据库性能瓶颈分析在 MySQL 的运行过程中&#xff0c;最核心的性能瓶颈来自磁盘 IO。磁盘访问延迟&#xff1a;一次机械硬盘 IO 操作可能需要数毫秒&#xff0c;即使是 SSD&#xff0c;访问延迟也在几十微秒量级。内存访问延迟&…

ArcGIS Pro 安装路径避坑指南:从崩溃根源到规范实操(附问题修复方案)

作为 GIS 从业者&#xff0c;你是否遇到过这些糟心场景&#xff1a;ArcGIS Pro 双击启动无响应、运行中突然弹出 “Runtime Error” 崩溃、加载矢量数据时提示 “找不到指定文件”&#xff1f;排查半天后发现&#xff0c;这些问题的 “元凶” 竟藏在安装路径里 —— 中文路径或…

Python 实战:内网渗透中的信息收集自动化脚本(2)

用途限制声明&#xff0c;本文仅用于网络安全技术研究、教育与知识分享。文中涉及的渗透测试方法与工具&#xff0c;严禁用于未经授权的网络攻击、数据窃取或任何违法活动。任何因不当使用本文内容导致的法律后果&#xff0c;作者及发布平台不承担任何责任。渗透测试涉及复杂技…

批量转双层PDF软件:高效转换,提升文档管理效率

在文档管理和信息检索中&#xff0c;双层PDF文件因其独特的结构而备受青睐。双层PDF文件不仅保留了原始文档的外观&#xff0c;还增加了对文档内容进行搜索和选择的功能&#xff0c;极大地提高了文档管理和信息检索的效率。批量转双层PDF软件正是为了解决这一需求而设计的&…

rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(七) 鼠标在控件上悬浮时的提示

文本提示on_hover_text ui.label("标签").on_hover_text("这是一个标签"); ui.text_edit_singleline(&mut edittext).on_hover_text("这是输入框"); if ui.button("提交").on_hover_text("这是一个按钮").clicked(){}提…