当前位置: 首页 > news >正文

linux shell编程实战 04 条件判断与流程控制

在Shell编程中,我们经常需要根据不同的情况执行不同的操作,或者重复执行某些命令。本章将学习如何通过条件判断和流程控制让脚本具备"判断能力"和"循环处理能力",这些都是编写实用脚本的核心知识。

4.1 条件判断基础:test命令与[]表达式

条件判断是指通过检查某个条件是否成立,来决定是否执行特定的命令。Shell中最基础的条件判断方式是test命令和[]表达式,它们功能完全相同,后者是前者的简化写法。

4.1.1 认识条件判断

简单来说,条件判断就像生活中的"如果…就…":

  • 如果文件存在,就处理它
  • 如果数值大于100,就发出警告
  • 如果字符串为空,就提示用户输入

在Shell中,条件判断的结果只有两种:成立(返回0)或不成立(返回非0)。我们可以通过$?变量查看上一个命令的返回值(0表示成功/成立,非0表示失败/不成立)。

4.1.2 使用test命令

test命令的基本语法:

test 条件

示例1:检查文件是否存在

# 检查当前目录是否有hello.sh文件
test -f "hello.sh"
echo $?  # 如果文件存在,输出0;否则输出1

示例2:检查字符串是否非空

# 检查变量是否有值
name="张三"
test -n "$name"
echo $?  # 输出0(字符串非空,条件成立)empty_str=""
test -n "$empty_str"
echo $?  # 输出1(字符串为空,条件不成立)

示例3:比较两个整数

a=10
b=20
test $a -lt $b  # -lt表示"小于"
echo $?  # 输出0(10<20成立)

4.1.3 使用[]表达式(推荐)

[]test命令的简化写法,更直观易用,语法:

[ 条件 ]  # 注意:条件前后必须有空格

示例:用[]重写上面的test命令

# 检查文件是否存在
[ -f "hello.sh" ]
echo $?# 检查字符串
name="张三"
[ -n "$name" ]
echo $?# 比较整数
a=10
b=20
[ $a -lt $b ]
echo $?

为什么推荐[]?

  • 写法更简洁,视觉上更像"条件判断"
  • 是Shell脚本中最常用的条件判断形式
  • 避免了test命令可能带来的语法歧义

4.1.4 常用条件类型及运算符

条件判断主要分为三类:文件测试、字符串测试和数值测试。

1. 文件测试(检查文件/目录属性)
运算符含义示例
-f 文件文件是否存在且为普通文件[ -f "test.txt" ]
-d 目录目录是否存在[ -d "mydir" ]
-e 路径路径(文件或目录)是否存在[ -e "path" ]
-r 文件文件是否存在且可读[ -r "test.txt" ]
-w 文件文件是否存在且可写[ -w "test.txt" ]
-x 文件文件是否存在且可执行[ -x "script.sh" ]

示例

file="test.txt"# 检查文件是否存在
if [ -e "$file" ]; thenecho "$file 存在"
elseecho "$file 不存在"
fi
2. 字符串测试(检查字符串属性或比较)
运算符含义示例
-n 字符串字符串是否非空(长度>0)[ -n "$name" ]
-z 字符串字符串是否为空(长度=0)[ -z "$empty" ]
字符串1 = 字符串2两个字符串是否相等[ "$a" = "$b" ]
字符串1 != 字符串2两个字符串是否不相等[ "$a" != "$b" ]

示例

username="admin"
input="admin"# 比较两个字符串是否相等
if [ "$input" = "$username" ]; thenecho "用户名正确"
elseecho "用户名错误"
fi

注意:字符串比较时,变量必须用双引号括起来,否则当变量为空时会导致语法错误。

3. 数值测试(整数比较)
运算符含义示例
num1 -eq num2等于(equal)[ 10 -eq 10 ]
num1 -ne num2不等于(not equal)[ 10 -ne 20 ]
num1 -gt num2大于(greater than)[ 20 -gt 10 ]
num1 -lt num2小于(less than)[ 10 -lt 20 ]
num1 -ge num2大于等于[ 10 -ge 10 ]
num1 -le num2小于等于[ 10 -le 20 ]

示例

age=17# 检查是否成年
if [ $age -ge 18 ]; thenecho "已成年"
elseecho "未成年"
fi

4.1.5 逻辑运算符(组合多个条件)

有时需要同时判断多个条件,这就需要用到逻辑运算符:

运算符含义用法
-a逻辑与(两个条件都成立)[ 条件1 -a 条件2 ]
-o逻辑或(至少一个条件成立)[ 条件1 -o 条件2 ]
!逻辑非(取反)[ ! 条件 ]

示例1:逻辑与(-a)

# 检查文件是否存在且可写
file="data.txt"
if [ -f "$file" -a -w "$file" ]; thenecho "$file 存在且可写"
elseecho "$file 不存在或不可写"
fi

示例2:逻辑非(!)

# 检查文件是否不存在
file="nonexistent.txt"
if [ ! -e "$file" ]; thenecho "$file 不存在,创建它..."touch "$file"  # 创建文件
fi

4.2 if语句:实现分支判断

if语句是Shell中最常用的流程控制结构,它能根据条件的真假执行不同的命令块。if语句有三种形式:单分支、双分支和多分支。

4.2.1 单分支if语句(如果…就…)

语法

if [ 条件 ]; then# 条件成立时执行的命令
fi

说明

  • then表示条件成立后要执行的命令块开始
  • fiif的反写,表示if语句结束
  • 条件成立时执行thenfi之间的命令,否则不执行

示例:检查文件是否存在,存在则输出内容

#!/bin/bash
file="test.txt"# 如果文件存在,就显示其内容
if [ -f "$file" ]; thenecho "$file 的内容如下:"cat "$file"  # 显示文件内容
fiecho "脚本执行结束"  # 无论条件是否成立,都会执行

4.2.2 双分支if-else语句(如果…就…否则…)

语法

if [ 条件 ]; then# 条件成立时执行
else# 条件不成立时执行
fi

说明

  • 条件成立执行then后的命令块
  • 条件不成立执行else后的命令块
  • 两个分支必选其一

示例:检查文件是否存在,不存在则创建

#!/bin/bash
file="notes.txt"if [ -f "$file" ]; thenecho "$file 已存在"
elseecho "$file 不存在,正在创建..."touch "$file"  # 创建文件echo "创建成功"
fi

4.2.3 多分支if-elif-else语句(多条件判断)

当需要判断多个条件时,使用if-elif-else结构:

语法

if [ 条件1 ]; then# 条件1成立时执行
elif [ 条件2 ]; then# 条件2成立时执行
elif [ 条件3 ]; then# 条件3成立时执行
else# 所有条件都不成立时执行(可选)
fi

说明

  • elif是"else if"的缩写,表示"否则如果"
  • 依次检查条件,找到第一个成立的条件后执行对应的命令块,然后跳过后续所有条件
  • else是可选的,当所有条件都不成立时执行

示例:根据分数判断等级

#!/bin/bash
read -p "请输入你的分数(0-100):" score# 先检查输入是否为有效的数字
if [ $score -lt 0 ] || [ $score -gt 100 ]; thenecho "错误:分数必须在0-100之间"
else# 根据分数判断等级if [ $score -ge 90 ]; thenecho "等级:优秀"elif [ $score -ge 80 ]; thenecho "等级:良好"elif [ $score -ge 60 ]; thenecho "等级:及格"elseecho "等级:不及格"fi
fi

4.2.4 if语句的嵌套

if语句内部可以再包含if语句,实现更复杂的判断逻辑:

示例:嵌套if判断

#!/bin/bash
read -p "请输入年龄:" ageif [ $age -ge 18 ]; thenecho "已成年"read -p "是否有身份证(y/n):" has_id# 嵌套if判断if [ "$has_id" = "y" ]; thenecho "可以办理银行卡"elseecho "请先办理身份证"fi
elseecho "未成年,无法办理银行卡"
fi

注意:嵌套层数不宜过多(建议不超过2层),否则会让脚本难以阅读和维护。

4.2.5 常见错误与注意事项

  1. 忘记写then
# 错误
if [ $a -gt 10 ]echo "a大于10"
fi# 正确
if [ $a -gt 10 ]; thenecho "a大于10"
fi
  1. 条件前后缺少空格
# 错误([和]前后必须有空格)
if [$a -gt 10]; then...
fi# 正确
if [ $a -gt 10 ]; then...
fi
  1. 字符串比较不用双引号
# 危险(如果var为空,会导致语法错误)
if [ $var = "test" ]; then...
fi# 安全
if [ "$var" = "test" ]; then...
fi

4.3 case语句:多值匹配判断

当需要判断一个变量与多个固定值匹配时,case语句比if-elif-else更简洁直观。比如处理菜单选择、命令行选项等场景。

4.3.1 case语句基本语法

case 变量 in值1)# 变量等于值1时执行;;值2)# 变量等于值2时执行;;值3)# 变量等于值3时执行;;*)# 变量不匹配任何值时执行(可选);;
esac

说明

  • case后面是要判断的变量
  • in是关键字,用于引入匹配的值列表
  • 每个"值)"后面是对应的命令块,以;;结束(表示跳出case)
  • *表示"其他所有情况",类似else
  • esaccase的反写,表示case语句结束

4.3.2 case语句示例

示例1:简单的菜单选择

#!/bin/bash
echo "请选择操作:"
echo "1. 查看日期"
echo "2. 查看当前目录"
echo "3. 查看系统时间"
echo "4. 退出"read -p "请输入选项(1-4):" choicecase $choice in1)echo "当前日期:$(date +%Y-%m-%d)";;2)echo "当前目录内容:"ls  # 显示当前目录文件;;3)echo "当前时间:$(date +%H:%M:%S)";;4)echo "再见!"exit 0  # 退出脚本;;*)echo "无效选项,请输入1-4";;
esac

示例2:判断输入的字符类型

#!/bin/bash
read -p "请输入一个字符:" charcase $char in[0-9])  # 匹配数字echo "你输入的是数字";;[a-z])  # 匹配小写字母echo "你输入的是小写字母";;[A-Z])  # 匹配大写字母echo "你输入的是大写字母";;*)  # 其他字符echo "你输入的是特殊字符";;
esac

4.3.3 case与if的选择

  • 当判断条件是多个固定值时,用case更简洁(如菜单选项)
  • 当需要进行范围判断(如>、<、>=)时,必须用if
  • 条件较少(2-3个)时,ifcase均可
  • 条件较多(4个以上)时,case更易读

4.4 流程控制辅助命令

Shell提供了几个辅助命令,用于控制脚本的执行流程,配合条件判断和循环使用。

4.4.1 exit命令:终止脚本执行

exit命令用于立即结束整个脚本的执行,并返回一个状态码:

语法

exit [状态码]
  • 状态码是0-255的整数,0表示"成功",非0表示"失败"
  • 不指定状态码时,默认使用上一个命令的退出状态码

示例:脚本出错时退出

#!/bin/bash
file="data.txt"# 检查文件是否存在,不存在则退出
if [ ! -f "$file" ]; thenecho "错误:$file 不存在"exit 1  # 非0状态码表示失败
fi# 文件存在则继续处理
echo "开始处理 $file..."
# 处理文件的命令...
exit 0  # 0表示成功结束

4.4.2 break和continue命令(提前了解)

这两个命令通常用于循环结构(下一章学习),但在这里先简单介绍:

  • break:跳出当前循环,不再执行后续循环
  • continue:跳过本次循环的剩余部分,直接进入下一次循环

示例(提前预览循环)

#!/bin/bash
# 打印1-10中的奇数(用continue跳过偶数)
echo "1-10中的奇数:"
for ((i=1; i<=10; i++)); doif [ $((i % 2)) -eq 0 ]; thencontinue  # 是偶数则跳过fiecho $i
done

4.5 实战示例:文件管理小工具

综合本章所学,编写一个简单的文件管理工具,实现创建、删除、查看文件等功能:

#!/bin/bash
# 文件管理小工具
# 功能:创建文件、删除文件、查看文件内容echo "===== 文件管理工具 ====="
echo "1. 创建新文件"
echo "2. 删除文件"
echo "3. 查看文件内容"
echo "4. 退出"
echo "======================"read -p "请选择功能(1-4):" choicecase $choice in1)read -p "请输入要创建的文件名:" filename# 检查文件是否已存在if [ -e "$filename" ]; thenread -p "$filename 已存在,是否覆盖?(y/n):" overwriteif [ "$overwrite" != "y" ]; thenecho "取消创建"exit 0fifi# 创建文件touch "$filename"echo "$filename 创建成功";;2)read -p "请输入要删除的文件名:" filename# 检查文件是否存在if [ ! -e "$filename" ]; thenecho "错误:$filename 不存在"exit 1fi# 确认删除read -p "确定要删除 $filename 吗?(y/n):" confirmif [ "$confirm" = "y" ]; thenrm "$filename"echo "$filename 已删除"elseecho "取消删除"fi;;3)read -p "请输入要查看的文件名:" filename# 检查文件是否存在且是普通文件if [ ! -f "$filename" ]; thenecho "错误:$filename 不存在或不是普通文件"exit 1fi# 检查文件是否为空if [ -s "$filename" ]; thenecho "$filename 的内容:"echo "----------------------"cat "$filename"echo "----------------------"elseecho "$filename 是空文件"fi;;4)echo "谢谢使用,再见!"exit 0;;*)echo "错误:无效选项,请输入1-4"exit 1;;
esac

脚本说明

  1. 使用case语句实现菜单选择
  2. 每个功能都有条件判断(文件是否存在、用户确认等)
  3. 用到了touch(创建文件)、rm(删除文件)、cat(查看文件)等基础Linux命令
  4. 有错误处理和用户交互,更贴近实际工具的使用场景

小结

本章学习了Shell中的条件判断与流程控制,主要内容包括:

  • 条件判断基础test命令和[]表达式的使用,以及文件测试、字符串测试、数值测试三类条件运算符
  • if语句:单分支(if)、双分支(if-else)、多分支(if-elif-else)的语法和应用场景,以及嵌套if的使用
  • case语句:多值匹配的语法和适用场景,与if语句的选择建议
  • 流程控制辅助命令exit(终止脚本)、breakcontinue(循环控制,下章详细学习)

这些知识是让脚本具备"判断能力"的核心,通过合理使用条件判断,脚本可以根据不同情况做出不同响应,大大提高灵活性。

下一章我们将学习循环结构,它能让脚本重复执行命令,非常适合批量处理任务(如批量重命名文件、批量处理数据等)。

http://www.dtcms.com/a/511266.html

相关文章:

  • 10.21云计算作业
  • 服务器数据恢复—EqualLogic存储硬硬盘坏道,数据恢复有妙招
  • 风险识别不充分会让项目付出什么代价
  • LeetCode 46. 全排列
  • 洛谷 - P13982 数列分块入门 7(线段树解法 - 超详细版)
  • 页面PDF文件格式预览(不使用pdf.js)
  • Prompt Engineering 关键技能:精准掌控 LLM 输出的格式、内容与风格
  • 苹果(IOS)制作开发和发布证书
  • iOS 上架技术支持全流程解析,从签名配置到使用 开心上架 的实战经验分享
  • ISO 15765系列标准在车载诊断系统中的具体应用有哪些?
  • 人体含水量测量体验系统-VR节约用水互动游戏
  • 【ArcGIS软件教程】数据导出、CAD转换、属性表导出、裁剪、空间连接、修复几何
  • XYlease租赁商城小程序
  • 上海做网站建设平面设计线上培训班哪个好
  • 硬件语言:verilog(1)
  • 全排列——交换的思想
  • 【系统架构设计师(第2版)】六、数据库设计基础知识
  • LeetCode每日一题——缀点成线
  • COM组件访问权限错误的解决方案‌错误信息:检索 COM 类工厂中 CLSID 为{xxxx} 的组件失败,原因是出现以下错误:80070005 拒绝访问
  • 计算机组成原理 刘宏伟 第四章 存储器(下)
  • MS-YOLOv11:一种用于遥感图像中小目标检测的小波增强多尺度网络
  • 外贸企业网站设计公司龙中龙网站开发
  • 整站优化seo做电脑网站手机能显示不出来怎么办
  • Android设备GPU频点挡位路径
  • Vanna Text2SQL框架:用自然语言查询数据库的新方式
  • Android Studio新手开发第二十七天
  • ros中的Navigation导航系统
  • Python循环结构、控制语句及综合应用问答
  • Typescript - Tuple 元祖类型(语法 / 简单使用 / 不可变元组 / 合并多个元组)详细入门教程
  • 成就系统概述