07-流程控制之while循环
所有练习题,建议
- 自己拿到需求主动思考,先尝试着写
- 然后再去借鉴看超哥的代码思路
- 自己再试试换一个写法
三部曲,冲冲冲。
为什么学while循环
在编程学习中,while循环是一项重要的基础技能,学习它主要有以下几个原因:
实现重复执行
- 提高效率:当需要重复执行一段代码时,使用while循环可以避免大量的代码重复书写。例如,在计算1到100的整数和时,使用while循环可以轻松实现,极大地提高了编程效率和代码的简洁性。
- 处理不确定次数的循环:在很多实际应用中,循环的次数往往是不确定的,需要根据特定条件来决定是否继续循环。比如,在用户登录验证功能中,用户可能会多次输入用户名和密码进行尝试,直到输入正确或达到最大尝试次数为止,while循环可以很好地处理这种情况。
构建程序逻辑
- 实现复杂逻辑控制:while循环可以与条件判断语句、分支语句等其他编程结构相结合,构建出非常复杂的程序逻辑。在游戏开发中,游戏的主循环通常使用while循环来实现,在循环中不断检测游戏状态、处理用户输入、更新游戏画面等,使得游戏能够持续运行并响应用户的操作。
- 模拟实际场景:现实生活中有很多场景可以用while循环来模拟。例如,在物流系统中,货物的装卸过程可能需要不断检查货物是否全部装卸完成,只要还有未装卸的货物,就需要继续执行装卸操作,这就可以使用while循环来模拟。
数据处理和算法实现
- 数据遍历和处理:在处理大量数据时,while循环常用于遍历数据集合,如数组、链表等。通过while循环可以逐个访问数据元素,并对其进行相应的处理,如查找特定元素、统计数据、数据转换等。
- 实现经典算法:许多经典的算法都依赖while循环来实现,如冒泡排序、插入排序、二分查找等。这些算法在计算机科学和数据处理中具有广泛的应用,理解和掌握while循环对于实现这些算法至关重要。
培养编程思维
- 条件判断和循环思维:学习while循环有助于培养条件判断和循环的编程思维方式。通过设置循环条件和更新循环变量,能够让学习者学会如何根据特定条件来控制程序的执行流程,以及如何在满足条件的情况下重复执行特定的操作,这种思维方式是编程中非常基础和重要的。
- 问题分解和解决能力:在使用while循环解决问题的过程中,需要将复杂的问题分解为多个简单的步骤,并通过循环和条件判断来逐步解决问题。这有助于提高学习者分析问题和解决问题的能力,培养逻辑思维和创造力。
1.while使用场景
1. 当明确循环的限定次数,用for、不确定循环次数使用while
2. 如循环让用户输入的登录程序
3. 如循环操作的一些菜单程序,直到用户输入结束指令菜单
2.while语法
在Bash脚本中,while
循环用于在给定条件为真时重复执行一组命令。以下为你详细介绍其语法、示例和使用场景。
基本语法
while [ condition ]
do
# 要执行的命令
command1
command2
...
done
[ condition ]
:这是一个测试条件,使用test
命令(通常用方括号[]
表示)来评估。只要该条件的返回状态码为0
(表示真),循环体中的命令就会不断执行。do
和done
:do
标记循环体的开始,done
标记循环体的结束,它们之间的所有命令构成了循环体。
案例
1. 简单的数字计数
下面的脚本会从 1 开始计数,直到数字达到 5 为止:
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo $count
count=$((count + 1))
done
解释:
count=1
:初始化一个变量count
并将其值设为 1。[ $count -le 5 ]
:检查count
是否小于或等于 5。echo $count
:打印当前count
的值。count=$((count + 1))
:将count
的值加 1。
2. 读取文件内容
下面的脚本逐行读取一个文件的内容:
#!/bin/bash
filename="/etc/passwd"
while IFS= read -r line
do
echo "$line"
done < "$filename"
解释:
IFS= read -r line
:IFS
是内部字段分隔符,这里将其设为空以防止行首和行尾的空格被删除;read -r
用于读取一行内容并将其存储到变量line
中,-r
选项可以防止反斜杠被转义。done < "$filename"
:使用输入重定向将文件内容作为while
循环的输入。
3. 用户输入验证
以下脚本会持续提示用户输入密码,直到输入正确的密码为止:
#!/bin/bash
correct_password="chaoge666"
while true
do
read -p "请输入密码: " password
if [ "$password" = "$correct_password" ]; then
echo "密码正确!"
break
else
echo "密码错误,请重试。"
fi
done
解释:
while true
:创建一个无限循环,因为true
命令总是返回状态码 0(真)。break
:当用户输入正确的密码时,使用break
语句跳出循环。
3.案例
循环限定范围
#!/bin/bash
# author: www.yuchaoit.cn
# 循环输出1~10
count=1
while [ $count -lt 10 ]
do
# 1~9
echo "数字:$count"
# count=$((count+1))
let count++
done
写法2
#!/bin/bash
# author: www.yuchaoit.cn
# 循环输出1~10
count=1
while [ $count -le 10 ]
do
echo "数字:$count"
count=$[$count+1]
done
按行循环读取文本
测试数据,且添加行号
我是云南的 云南怒江的
爱你孤身走暗巷
爱你不跪的模样
爱你对峙过绝望
不肯哭一场
写法1
#!/bin/bash
# author: www.yuchaoit.cn
# 利用exec读取文本数据
# 文件数据,直接加载到bash脚本环境下,独立开辟bash子进程
# exec < t.log 将脚本的标准输入重定向到文件 t.log。
这意味着后续的 read 命令将从 t.log 文件中读取内容,而不是从标准输入(如键盘输入)读取。
exec < t.log
line_num=1
while read txt
do
# cat -n
echo "$line_num $txt"
let line_num++
done
写方法2
#!/bin/bash
# author: www.yuchaoit.cn
line_num=1
while read txt
do
echo "$line_num $txt"
let line_num++
done < t.log
写法3
#!/bin/bash
# author: www.yuchaoit.cn
line_num=1
cat t.log|while read txt
do
echo "$line_num $txt"
let line_num++
done
while文件读取
在Bash脚本中,你可以使用while
循环按行读取文本文件。下面为你详细介绍几种常见的实现方式及示例代码。
方法一:使用read
命令结合while
循环
read
命令用于从标准输入或文件中读取一行内容,结合while
循环可以逐行处理文件内容。以下是示例代码:
#!/bin/bash
# 定义要读取的文件路径
file="example.txt"
# 使用while循环和read命令逐行读取文件
while IFS= read -r line; do
# 打印每一行内容
echo "$line"
# 这里可以添加更多对每一行的处理逻辑
done < "$file"
代码解释:
IFS=
:IFS
(内部字段分隔符)默认包含空格、制表符和换行符。将IFS
设置为空,避免read
命令在读取行时对行内容进行分词操作,确保整行内容被完整读取。read -r line
:-r
选项用于禁止read
命令对反斜杠进行转义处理,将读取的每一行内容存储到变量line
中。done < "$file"
:使用输入重定向将文件$file
的内容作为while
循环的输入。
方法二:使用cat
命令结合管道
你也可以使用cat
命令读取文件内容,并通过管道将其传递给while
循环。示例代码如下:
#!/bin/bash
# 定义要读取的文件路径
file="example.txt"
# 使用cat命令读取文件内容并通过管道传递给while循环
cat "$file" | while IFS= read -r line; do
# 打印每一行内容
echo "$line"
# 这里可以添加更多对每一行的处理逻辑
done
代码解释:
cat "$file"
:读取文件$file
的内容。|
:管道符号,将cat
命令的输出作为while
循环的输入。
注意事项
- 子shell问题:使用管道时,
while
循环会在子shell中执行。这意味着在while
循环中对变量的修改不会影响到父shell中的变量。如果需要在循环结束后访问循环内修改的变量,建议使用方法一。 - 文件存在性检查:在实际使用中,建议在读取文件前检查文件是否存在,避免因文件不存在而导致的错误。示例代码如下:
```bash
!/bin/bash
定义要读取的文件路径
file="example.txt"
检查文件是否存在
if [ -f "$file" ]; then while IFS= read -r line; do echo "$line" done < "$file" else echo "文件 $file 不存在。" fi
你可以将上述代码保存为一个`.sh`文件,赋予执行权限后运行,即可按行读取文本文件。
# 4.练习题
## 循环累加1到100
1+2+3+...+100
!/bin/bash
author: www.yuchaoit.cn
sum=0 count=1
while [ $count -le 100 ] do sum=$[$sum+$count] let count++ done
echo "sum总和:$sum"
## 循环累加1到100的偶数
!/bin/bash
author: www.yuchaoit.cn
sum=0 count=0
while [ $count -le 100 ] do sum=$[$sum+$count] count=$[count+2] done
echo "sum总和:$sum"
反之奇数如何求?试试写法
## 1~9的计算表达式
完成1 ~ 9 的计算表达式
打印如下内容
9 9 = 81 8 8 = 64 7 7 = 49 6 6 = 36 5 5 = 25 4 4 = 16 3 3 = 9 2 2 = 4 1 * 1 = 1
代码
!/bin/bash
author: www.yuchaoit.cn
num=9 while [ $num -ge 1 ] do echo "$num $num = $[ $num $num ]" num=$[$num-1] done
再打印如下
91 =9 82 =16 73 =21 64 =24 55 =25 46 =24 37 =21 28 =16 1*9 =9
代码
!/bin/bash
author: www.yuchaoit.cn
n1=9 n2=1 while [ $n1 -ge 1 -a $n2 -le 9 ] do echo "$n1 $n2 = $[ $n1 $n2 ]" n1=$[$n1-1] n2=$[$n2+1] done
## 测试while条件成立
死循环提示用户输入账号 猜对后结束程序
代码
!/bin/bash
author: www.yuchaoit.cn
while [ "$u" != "sunwukong" ] do read -p "请输入账号 sunwukong:" u done
## 读取文件数据,创建系统用户
测试数据
[root@www.yuchaoit.cn ~]#cat u.log yuchao01:1500:1234567:devops bob01:1501:1234567:sre jack01:1502:123456:dba
创建用户,指定 username uid password groups
要求做好用户检测,不得反复检测
脚本
!/bin/bash
author: www.yuchaoit.cn
exec < u.log while read line do groups=$(echo $line|awk -F':' '{print $4}') uid=$(echo $line|awk -F':' '{print $2}') password=$(echo $line|awk -F':' '{print $3}') username=$(echo $line|awk -F':' '{print $1}')
# 组判断
grep "$groups" /etc/group &>/dev/null
if [ $? -ne 0 ];then
echo "该$groups 不存在,创建中.."
groupadd $groups
fi
echo '============================================================'
# 用户创建
grep "$username" /etc/passwd &>/dev/null
if [ $? -ne 0 ];then echo "该$username 不存在,创建中.." useradd $username -u $uid -G $groups echo $password | passwd --stdin $username fi
用户检查
echo "用户信息是:$(id $username)"
done
## 猜数字
需求
- 随机生成1~100数字
- 提示用户只能输入数字,做好程序判断
- 友好提示,猜大了、猜小了
- 死循环,只有猜对后结束程序
- 统计猜了几次(只统计正确输入) ```
代码
#!/bin/bash
# author: www.yuchaoit.cn
# 取余,限制随机数范围在0~99
r_num=$(echo $[RANDOM%100+1])
guess_count=0
# 程序开始
while true
do
read -p "====下定离手!!请输入数字===:" num
# 限制数字
if [ -z $(echo $num |sed -rn '/^[0-9]+$/p') ];then
echo "大哥,请输入纯数字,你会不会玩啊?"
continue
fi
# 每次循环,统计+1
let guess_count++
if [ $num -gt $r_num ];then
echo "你太大了。。"
elif [ $num -lt $r_num ];then
echo "你太小了"
else
echo "恭喜你,猜对了!!!随机数字是$r_num,一共猜了$guess_count次!!"
exit
fi
done
5.while运维脚本
以下为你提供几个不同运维场景下使用 Bash while
循环开发的脚本示例:
1. 监控进程是否存在,若不存在则启动
在服务器运维中,需要保证某些关键进程时刻处于运行状态。以下脚本会持续监控指定进程是否存在,若不存在则启动该进程。
#!/bin/bash
# 要监控的进程名
process_name="redis"
# 启动进程的命令
start_command="systemctl start redis"
# 每隔5秒进程一次程序检查,如果挂了,自动启动
while true; do
# 检查进程是否存在
if ! pgrep "$process_name" > /dev/null; then
echo "$(date): $process_name is not running. Starting it now..."
$start_command
if [ $? -eq 0 ]; then
echo "$(date): $process_name has been started successfully."
else
echo "$(date): Failed to start $process_name."
fi
else
echo "$process_name 健康运行中!"
fi
# 每隔 5 秒检查一次
sleep 5
done
代码解释:
while true
:创建一个无限循环,使脚本持续运行。pgrep "$process_name"
:检查指定名称的进程是否存在。$start_command
:若进程不存在,执行启动进程的命令。sleep 5
:每隔 5 秒进行一次检查,避免过于频繁占用系统资源。
2. 监控磁盘使用率,超过阈值则发送警报
在运维中,需要关注磁盘的使用情况,当磁盘使用率超过某个阈值时,需要及时发出警报。
#!/bin/bash
# 磁盘挂载点
mount_point="/"
# 使用率阈值(百分比)
threshold=80
while true; do
# 获取磁盘使用率
usage=$(df -h "$mount_point" | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $usage -gt $threshold ]; then
echo "$(date): Disk usage on $mount_point is $usage%. Exceeded threshold of $threshold%."
# 这里可以添加发送邮件或其他警报机制
fi
# 每隔 10 分钟检查一次
sleep 600
done
代码解释:
df -h "$mount_point"
:获取指定挂载点的磁盘使用信息。awk 'NR==2 {print $5}'
:提取第二行的第五列(即使用率)。sed 's/%//'
:去除百分号,方便后续比较。if [ $usage -gt $threshold ]
:若使用率超过阈值,输出警报信息。sleep 600
:每隔 10 分钟(600 秒)检查一次。
3. 批量处理文件
假设需要对某个目录下的所有文件进行批量重命名,将文件名中的特定字符串替换为另一个字符串。
#!/bin/bash
# 目录路径
directory="/path/to/your/directory"
# 要替换的字符串
old_string="old"
# 替换后的字符串
new_string="new"
# 获取目录下的所有文件
files=$(ls "$directory")
while read -r file; do
new_file=$(echo "$file" | sed "s/$old_string/$new_string/g")
mv "$directory/$file" "$directory/$new_file"
echo "Renamed $file to $new_file"
done <<< "$files"
代码解释:
ls "$directory"
:获取指定目录下的所有文件。while read -r file
:逐行读取文件列表。sed "s/$old_string/$new_string/g"
:将文件名中的旧字符串替换为新字符串。mv
:重命名文件。
以上脚本可以根据实际需求进行修改和扩展,以满足不同的运维业务场景。