shell控制语句
Shell 脚本程序控制语句:脚本的决策与循环大脑
引言:让脚本学会思考与重复
想象一下,你是一个指挥官,正在给部队下达指令:
- 如果(if)发现敌人,立即开火。
- 只要(while)阵地上还有敌人,就继续攻击。
- 对弹药库里的每一种(for)武器进行检查。
- 如果弹药耗尽,跳出(break)当前战斗,执行撤退计划。
- 如果只是小股敌人,跳过(continue)重武器,使用步枪解决。
如果没有这些控制指令,你的命令将是混乱且低效的。同样,Shell 脚本中的程序控制语句就是它的“决策大脑”和“循环引擎”,它让脚本不再是简单粗暴地顺序执行每一条命令,而是能够根据条件做出判断、重复执行任务、选择不同的执行路径。
掌握了控制语句,你的脚本就拥有了真正的“智能”,能够应对各种复杂场景。本文将带你深入浅出地学习 Shell 脚本中所有这些强大的控制结构。
一、条件判断:如果…就…(if/else)
条件判断是脚本最基础的分支能力,让它能够“审时度势”。
1.1 基础 if 语法
if [ 条件 ]; then |
示例:检查文件是否存在
|
1.2 如果…就…否则…(if/else)
if [ 条件 ]; then |
示例:判断用户输入
|
1.3 多条件判断(if/elif/else)
if [ 条件1 ]; then |
示例:成绩等级划分
|
1.4 条件测试的基石:test 命令与 [ ]
Shell 中的条件判断依赖于 test 命令。[ condition ] 实际上是 test condition 的另一种写法(注意 [ 后和 ] 前必须有空格!)。
常用测试运算符:
| 类别 | 运算符 | 含义 | 示例 |
|---|---|---|---|
| 文件测试 | -e file |
文件/目录是否存在 | [ -e "/tmp" ] |
-f file |
是否是文件 | [ -f "log.txt" ] |
|
-d file |
是否是目录 | [ -d "/home" ] |
|
-r file |
文件是否可读 | [ -r "data.txt" ] |
|
-w file |
文件是否可写 | [ -w "config.cfg" ] |
|
-x file |
文件是否可执行 | [ -x "app.sh" ] |
|
-s file |
文件长度是否 > 0(非空) | [ -s "output.log" ] |
|
| 字符串比较 | -z str |
字符串长度是否为 0 | [ -z "$var" ] |
-n str |
字符串长度是否非 0 | [ -n "$var" ] |
|
str1 = str2 |
字符串是否相等 | [ "$a" = "$b" ] |
|
str1 != str2 |
字符串是否不相等 | [ "$a" != "$b" ] |
|
| 算术比较 | num1 -eq num2 |
等于 (Equal) | [ 5 -eq 5 ] ✅ |
num1 -ne num2 |
不等于 (Not Equal) | [ 5 -ne 3 ] ✅ |
|
num1 -gt num2 |
大于 (Greater Than) | [ 10 -gt 5 ] ✅ |
|
num1 -lt num2 |
小于 (Less Than) | [ 1 -lt 4 ] ✅ |
|
num1 -ge num2 |
大于等于 (Greater or Equal) | [ 5 -ge 5 ] ✅ |
|
num1 -le num2 |
小于等于 (Less or Equal) | [ 3 -le 5 ] ✅ |
|
| 逻辑操作 | ! |
非 (NOT) | [ ! -f "$file" ] |
-a 或 && |
与 (AND) | [ "$a" -gt 0 -a "$a" -lt 10 ] [[ $a -gt 0 && $a -lt 10 ]] |
|
-o 或 || |
或 (OR) | [ "$ans" = "y" -o "$ans" = "Y" ] [[ $ans = "y" || $ans = "Y" ]] |
注意:
&&和||通常在更强大的[[ ]]条件结构中使用,它比[ ]更通用,且能防止一些逻辑错误。
二、分支选择:情况…(case)
当需要根据一个变量的多种不同值来执行不同操作时,case 语句比一堆 elif 更清晰、更高效。
2.1 case 语法结构
case $变量 in |
示例:简单的命令解析器
|
三、循环处理:重复的艺术
循环让你可以一遍又一遍地执行相同的代码块,直到满足某个条件。
3.1 for 循环:遍历列表
语法一:遍历值列表
for 变量 in 项1 项2 项3 ... 项N |
示例:处理多个文件
|
语法二:C 语言风格的 for 循环
for (( 初始值; 条件; 步进 )) |
示例:数字迭代
|
3.2 while 循环:只要条件为真,就继续循环
while 循环会在循环开始时检查条件,只要条件为真(返回状态码为 0),就继续执行循环体。
while [ 条件 ] |
示例:计数器
|
经典用法:读取文件每一行
|
3.3 until 循环:直到条件为真,才停止循环
until 与 while 相反。它一直循环,直到条件变为真为止。
until [ 条件 ] |
示例:等待某个进程启动
|
四、循环控制:break 与 continue
这两个命令用于在循环内部进行更精细的控制。
4.1 break:立即跳出循环
break 用于无条件地终止并跳出当前循环,执行 done 后面的命令。
示例:在数组中查找元素,找到后立即退出
|
跳出多层循环:break n 可以跳出 n 层循环。
for ((i=1; i<=3; i++)) |
4.2 continue:跳过本次循环
continue 用于跳过当前循环中剩余的语句,直接开始下一次循环。
示例:只处理奇数
|
五、实战综合案例:自动化备份脚本
让我们用一个融合了多种控制语句的实战案例来结束本章。
|
总结与最佳实践
Shell 的控制语句赋予了脚本灵魂,使其变得强大而灵活。
选择合适的工具:
if/case用于分支选择。for适合已知循环次数或遍历集合。while/until适合未知循环次数,取决于某个条件。
重要提醒:
- 空格是语法:在
[ ]、[[ ]]、(( ))中,括号内的空格是必须的,否则会报错。 - 变量加引号:在
[ ]中引用变量时,最好用双引号括起来,如[ -f "$file" ],以防止变量为空或含空格导致语法错误。 - 使用
[[ ]]:在现代 Bash 脚本中,优先使用[[ ]]进行条件测试,它比[ ]更强大、更安全(支持&&,||,=~正则匹配等)。 - 算术比较用
(( )):进行数字计算和比较时,使用(( ))更直观,如if (( count > 10 )); then ...。
- 空格是语法:在
通过熟练组合运用条件判断、分支选择和各种循环,你将能够解决 Shell 环境中绝大多数自动化任务和系统管理问题。
