主题
Shell循环结构(for/while)
课程介绍
循环是编程语言的核心功能之一,Shell脚本通过for循环和while循环实现重复执行代码块。本课程将详细讲解Shell循环的语法、使用场景以及break和continue语句,帮助你掌握Shell脚本中的循环控制逻辑。
1. for循环
1.1 for循环基本语法
Shell的for循环有多种语法形式。
语法1:遍历列表
bash
for 变量 in 列表
do
代码块
done语法2:遍历文件
bash
for 变量 in 文件模式
do
代码块
done语法3:C语言风格
bash
for ((初始化; 条件; 更新))
do
代码块
done1.2 遍历列表
for循环最常用的场景是遍历列表。
示例1:遍历数字列表
bash
#!/bin/bash
# 遍历数字列表
for num in 1 2 3 4 5
do
echo "数字:$num"
done示例2:遍历字符串列表
bash
#!/bin/bash
# 遍历字符串列表
for fruit in 苹果 香蕉 橙子 葡萄
do
echo "水果:$fruit"
done示例3:使用seq生成序列
bash
#!/bin/bash
# 使用seq生成序列
for num in $(seq 1 10)
do
echo "数字:$num"
done1.3 遍历文件
for循环可以遍历文件和目录。
示例1:遍历文件
bash
#!/bin/bash
# 遍历当前目录的所有文件
for file in *.txt
do
echo "文件:$file"
done示例2:遍历目录
bash
#!/bin/bash
# 遍历当前目录的所有目录
for dir in */
do
echo "目录:$dir"
done示例3:递归遍历文件
bash
#!/bin/bash
# 递归遍历文件
for file in $(find /data -name "*.txt")
do
echo "文件:$file"
done1.4 C语言风格的for循环
Shell支持类似C语言的for循环语法。
示例1:数字循环
bash
#!/bin/bash
# C语言风格的for循环
for ((i=1; i<=10; i++))
do
echo "数字:$i"
done示例2:步长循环
bash
#!/bin/bash
# 步长为2的循环
for ((i=0; i<=10; i+=2))
do
echo "数字:$i"
done示例3:倒序循环
bash
#!/bin/bash
# 倒序循环
for ((i=10; i>=1; i--))
do
echo "数字:$i"
done2. while循环
2.1 while循环基本语法
while循环在条件为真时重复执行代码块。
基本语法:
bash
while [ 条件 ]
do
代码块
done2.2 while循环示例
示例1:数字循环
bash
#!/bin/bash
# while循环
i=1
while [ $i -le 10 ]
do
echo "数字:$i"
i=$((i+1))
done示例2:读取文件
bash
#!/bin/bash
# 读取文件
while read line
do
echo "行:$line"
done < /etc/passwd示例3:无限循环
bash
#!/bin/bash
# 无限循环
while true
do
echo "Hello, World!"
sleep 1
done2.3 until循环
until循环在条件为假时重复执行代码块。
基本语法:
bash
until [ 条件 ]
do
代码块
done示例:
bash
#!/bin/bash
# until循环
i=1
until [ $i -gt 10 ]
do
echo "数字:$i"
i=$((i+1))
done3. break和continue
3.1 break语句
break语句用于跳出循环。
示例1:跳出for循环
bash
#!/bin/bash
# 跳出for循环
for i in {1..10}
do
if [ $i -eq 5 ]; then
break
fi
echo "数字:$i"
done示例2:跳出while循环
bash
#!/bin/bash
# 跳出while循环
i=1
while true
do
if [ $i -gt 10 ]; then
break
fi
echo "数字:$i"
i=$((i+1))
done3.2 continue语句
continue语句用于跳过当前循环迭代。
示例1:跳过for循环的迭代
bash
#!/bin/bash
# 跳过for循环的迭代
for i in {1..10}
do
if [ $((i % 2)) -eq 0 ]; then
continue
fi
echo "奇数:$i"
done示例2:跳过while循环的迭代
bash
#!/bin/bash
# 跳过while循环的迭代
i=1
while [ $i -le 10 ]
do
i=$((i+1))
if [ $((i % 2)) -eq 0 ]; then
continue
fi
echo "奇数:$i"
done4. 循环嵌套
4.1 嵌套for循环
for循环可以嵌套使用。
示例1:九九乘法表
bash
#!/bin/bash
# 九九乘法表
for i in {1..9}
do
for j in {1..9}
do
if [ $j -le $i ]; then
echo -n "$j*$i=$((i*j)) "
fi
done
echo ""
done示例2:遍历目录和文件
bash
#!/bin/bash
# 遍历目录和文件
for dir in */
do
echo "目录:$dir"
for file in $dir/*
do
echo " 文件:$file"
done
done4.2 嵌套while循环
while循环也可以嵌套使用。
示例:
bash
#!/bin/bash
# 嵌套while循环
i=1
while [ $i -le 3 ]
do
echo "外层循环:$i"
j=1
while [ $j -le 3 ]
do
echo " 内层循环:$j"
j=$((j+1))
done
i=$((i+1))
done5. 完整示例
示例1:批量重命名文件
bash
#!/bin/bash
# 批量重命名文件
# 遍历所有.txt文件
for file in *.txt
do
# 获取文件名(不含扩展名)
filename=$(basename "$file" .txt)
# 重命名文件
mv "$file" "${filename}.bak"
echo "重命名:$file -> ${filename}.bak"
done示例2:批量创建用户
bash
#!/bin/bash
# 批量创建用户
# 用户列表
users=("user1" "user2" "user3" "user4" "user5")
# 遍历用户列表
for user in "${users[@]}"
do
# 检查用户是否已存在
if id "$user" &>/dev/null; then
echo "用户 $user 已存在"
continue
fi
# 创建用户
useradd "$user"
# 设置密码
echo "$user:123456" | chpasswd
echo "用户 $user 创建成功"
done示例3:批量处理文件
bash
#!/bin/bash
# 批量处理文件
# 遍历所有.log文件
for file in *.log
do
# 统计行数
lines=$(wc -l < "$file")
# 统计错误数量
errors=$(grep -c "ERROR" "$file")
# 输出统计信息
echo "文件:$file"
echo " 行数:$lines"
echo " 错误数:$errors"
echo ""
done示例4:监控目录变化
bash
#!/bin/bash
# 监控目录变化
# 监控目录
dir="/data/upload"
# 获取初始文件列表
old_files=$(ls "$dir")
# 无限循环
while true
do
# 获取当前文件列表
new_files=$(ls "$dir")
# 比较文件列表
if [ "$old_files" != "$new_files" ]; then
echo "目录 $dir 发生变化"
echo " 新文件列表:$new_files"
# 更新文件列表
old_files=$new_files
fi
# 等待1秒
sleep 1
done示例5:批量下载文件
bash
#!/bin/bash
# 批量下载文件
# 文件列表
files=("file1.txt" "file2.txt" "file3.txt")
# 下载目录
download_dir="/data/download"
# 创建下载目录
mkdir -p "$download_dir"
# 遍历文件列表
for file in "${files[@]}"
do
# 下载文件
wget "https://example.com/$file" -O "$download_dir/$file"
# 检查下载是否成功
if [ $? -eq 0 ]; then
echo "下载成功:$file"
else
echo "下载失败:$file"
fi
done6. 循环性能优化
6.1 避免在循环中执行耗时操作
bash
# 不好的做法
for file in *.txt
do
# 在循环中执行耗时操作
count=$(find . -name "*.txt" | wc -l)
done
# 好的做法
# 在循环外执行耗时操作
count=$(find . -name "*.txt" | wc -l)
for file in *.txt
do
echo "文件:$file"
done6.2 使用数组代替多个变量
bash
# 不好的做法
file1="file1.txt"
file2="file2.txt"
file3="file3.txt"
# 好的做法
files=("file1.txt" "file2.txt" "file3.txt")
for file in "${files[@]}"
do
echo "文件:$file"
done6.3 使用并行处理
bash
# 使用xargs并行处理
find . -name "*.txt" | xargs -P 4 -I {} sh -c 'echo "处理:{}"'
# 使用GNU parallel并行处理
find . -name "*.txt" | parallel -j 4 echo "处理:{}"课程总结
这节课我们学习了Shell循环结构。
核心内容:
- for循环(遍历列表、遍历文件、C语言风格)
- while循环
- until循环
- break和continue语句
- 循环嵌套
- 完整示例
- 循环性能优化
重要命令:
for ... in ... do ... done:for循环while ... do ... done:while循环until ... do ... done:until循环break:跳出循环continue:跳过当前迭代seq:生成序列find:查找文件
循环是Shell脚本编程的核心,掌握这些知识后,我们将在后续课程中学习函数、文件操作等高级特性。
课后练习
练习1(基础)
创建一个脚本,要求:
- 使用for循环输出1-10的数字
- 使用while循环输出1-10的数字
- 使用until循环输出1-10的数字
练习2(进阶)
创建一个脚本,要求:
- 遍历当前目录的所有.txt文件
- 统计每个文件的行数
- 输出文件名和行数
练习3(拓展)
创建一个脚本,要求:
- 使用嵌套循环输出九九乘法表
- 使用for循环和while循环实现