linux shell 编程:while循环

介绍

shell 的 while 属于条件循环:条件为真,就一直循环;条件假,退出循环

一、基础语法

每次先执行条件表达式,返回 0(成功/真) 就进入 do 里面执行代码;非0(失败/假)跳出循环。

while 测试命令
do
    命令1
    命令2
done

重点:while 后面不是括号表达式,是一条命令,命令返回码 $? 决定循环是否继续。

最常用:[ ](test命令)、[[ ]] 增强判断,也可以直接放普通命令(如 read)。

示例1:数字递增循环

#!/bin/bash
i=1
while [ $i -le 5 ]   # i <=5
do
    echo "i = $i"
    i=$((i+1))      # 自增,不能漏!否则死循环
done

输出:

i = 1
i = 2
i = 3
i = 4
i = 5

⚠️ 坑:忘记修改循环变量 → 死循环,按 Ctrl + C 终止。


二、while 条件写法分类

1. 使用 [ ](标准test,兼容所有sh)

while [ $i -gt 0 ]
do
  echo $i
  i=$((i-1))
done

2. [[ ]] bash增强版(推荐bash脚本)

支持正则、&& ||,不容易踩引号坑

while [[ $i -gt 0 && $name != "stop" ]]
do
  ...
done

3. 直接跟命令(非常常用!)

只要命令执行成功就循环。

# 每隔1秒打印时间,直到ctrl+c
while sleep 1
do
    date
done

sleep 1 返回0,条件永远为真 → 死循环。

4. 无限死循环写法

两种等价写法:

# 写法1 true命令永远返回0
while true
do
    echo "无限循环"
    sleep 1
done

# 写法2 : 是空命令,返回0
while :
do
    echo "无限循环"
    sleep 1
done

三、while 读取文件(高频场景)

✅ 方式1:while read 逐行读文件(推荐)

#!/bin/bash
# 读取 test.txt 每一行,变量line保存每行内容
while read line
do
    echo "行内容:$line"
done < test.txt

< test.txt 是输入重定向,把文件作为 read 的标准输入。

带字段分割:读取多列文本

文件内容(user.txt)

zhangsan 20
lisi 25
wangwu 30

脚本:

while read name age
do
    echo "姓名:$name,年龄:$age"
done < user.txt

read 默认按空白(空格/tab)分割,一行多个值依次赋值变量。

注意:read 默认会自动去掉行尾换行符;遇到\会换行续读,可加 -r 禁止反斜杠转义:

while read -r line
do
  echo "$line"
done < test.txt

read -r 写读取文件脚本的最佳实践,防止 \ 被解析为转义符

❗ 坑:管道方式 while 会开子shell

# 不推荐!管道 | 会开启子shell,循环内部修改的变量外部不生效
cat test.txt | while read line
do
    count=$((count+1))
done
echo $count # count还是0!

原因:管道右边命令运行在子进程,变量无法回写到父shell。优先用输入重定向 <


四、循环控制

  1. break:立刻跳出整个while循环,执行done后面代码
  2. continue:跳过本次循环剩余代码,直接进入下一轮条件判断

break

i=1
while [ $i -le 10 ]
do
    if [ $i -eq 5 ];then
        break   # i=5 直接退出循环
    fi
    echo $i
    i=$((i+1))
done

continue

i=0
while [ $i -lt 10 ]
do
    i=$((i+1))
    if [ $i -eq 5 ];then
        continue # i=5,跳过echo,直接下一轮
    fi
    echo $i
done
# 输出1 2 3 4 6 7 8 9 10

break 可以加数字:break 2 跳出两层嵌套循环;continue同理 continue 2

嵌套while示例

a=1
while [ $a -le 3 ]
do
    b=1
    while [ $b -le 3 ]
    do
        if [ $b -eq 2 ];then
            break 2 # 一次性跳出内外两层while
        fi
        echo "a=$a b=$b"
        b=$((b+1))
    done
    a=$((a+1))
done

五、输入重定向 & here-string / here-doc 配合while

Here-doc 给while传输入

while read name
do
    echo "name: $name"
done <<EOF
Tom
Jack
Mary
EOF

Here-string

while read line
do
    echo $line
done <<<"第一行
第二行"

六、while 与 until 的简单对比

  • while 条件:条件为真就循环
  • until 条件:条件为假就循环
    i=1
    until [ $i -gt 5 ]
    do
      echo $i
      i=$((i+1))
    done
    

七、常见坑

  1. 变量比较:[ ] 前后必须空格,[$i -le 5] 语法报错!要写 [ $i -le 5 ]
  2. 数字运算:i=i+1 是字符串拼接,必须 i=$((i+1))
  3. read 不加 -r,行里的 \ 会被吃掉
  4. cat file | while read → 子shell,变量失效,优先 < 重定向
  5. 字符串比较,变量最好双引号包裹 [ "$var" = "abc" ],防止空值报错
  6. 死循环:while true,终止快捷键 Ctrl + C

八、练习题(可直接复制运行)

#!/bin/bash
# 计算1~10累加
sum=0
i=1
while [ $i -le 10 ]
do
    sum=$((sum+i))
    i=$((i+1))
done
echo "sum=$sum"

如果你需要,我可以再写:

  1. while读取csv、带IFS自定义分隔符的案例
  2. while监控进程/端口的运维脚本模板
  3. while的退出码、重定向异常处理详解