07-流程控制之while循环

所有练习题,建议

  1. 自己拿到需求主动思考,先尝试着写
  2. 然后再去借鉴看超哥的代码思路
  3. 自己再试试换一个写法

三部曲,冲冲冲。

为什么学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(表示真),循环体中的命令就会不断执行。
  • dodonedo 标记循环体的开始,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 lineIFS 是内部字段分隔符,这里将其设为空以防止行首和行尾的空格被删除;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"

代码解释:

  1. IFS=IFS(内部字段分隔符)默认包含空格、制表符和换行符。将IFS设置为空,避免read命令在读取行时对行内容进行分词操作,确保整行内容被完整读取。
  2. read -r line-r选项用于禁止read命令对反斜杠进行转义处理,将读取的每一行内容存储到变量line中。
  3. 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. 随机生成1~100数字
  2. 提示用户只能输入数字,做好程序判断
  3. 友好提示,猜大了、猜小了
  4. 死循环,只有猜对后结束程序
  5. 统计猜了几次(只统计正确输入) ```

代码

#!/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:重命名文件。

以上脚本可以根据实际需求进行修改和扩展,以满足不同的运维业务场景。

Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2025-01-30 15:59:03

results matching ""

    No results matching ""