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

Shell 脚本判断

Shell 脚本判断

一、条件测试基础

在 Shell 脚本中,“判断” 的核心是通过条件测试判断表达式真假,进而控制程序流程。条件测试的核心要素包括:测试类型、表达式格式、结果判断逻辑。

1. 条件测试的 3 种类型

Shell 支持三类常见的条件测试,覆盖整数、字符、文件场景:

测试类型

作用

核心场景

整数测试

比较两个整数的大小关系(相等、大于、小于等)

数值比较(如参数数量判断、年龄 / 分数比较)

字符测试

检查字符串的内容、长度或等值关系

字符串是否为空、输入内容匹配(如用户名验证)

文件测试

检测文件 / 目录的存在性、类型、权限、大小等

文件是否存在、是否为目录、是否有执行权限

2. 条件测试的 3 种表达式格式

所有条件测试均需通过固定格式的表达式实现,三种格式功能等价,可根据场景选择:

表达式格式

语法示例

说明

test 条件

test -e /tmp/file

最原始的格式,兼容性好

[ 条件 ]

[ -e /tmp/file ]

简化格式,需注意条件前后有空格(否则语法错误)

[[ 条件 ]]

[[ -e /tmp/file ]]

Bash 扩展格式,支持正则匹配(如 [[ $str =~ ^[0-9]+$ ]]),推荐使用

3. 结果判断逻辑

条件测试的结果通过退出状态码(0 为真,非 0 为假)表示,通常结合逻辑运算符 &&(真则执行)和 ||(假则执行)输出结果:

# 示例:测试 /tmp/file 是否存在test -e /tmp/file && echo "文件存在" || echo "文件不存在"[ -e /tmp/file ] && echo "文件存在" || echo "文件不存在"[[ -e /tmp/file ]] && echo "文件存在" || echo "文件不存在"
  • 若 /tmp/file 存在,输出 文件存在;若不存在,输出 文件不存在。

二、整数测试(数值比较)

整数测试用于比较两个整数的大小关系,需使用专用的比较运算符(不可用 > < 等符号,避免与字符比较混淆)。

1. 整数测试运算符

运算符

含义

示例(判断 $a 和 $b 的关系)

-eq

等于(equal)

[[ $a -eq $b ]] → 判断 $a 是否等于 $b

-ne

不等于(not equal)

[[ $a -ne $b ]] → 判断 $a 是否不等于 $b

-gt

大于(greater than)

[[ $a -gt $b ]] → 判断 $a 是否大于 $b

-ge

大于等于(greater or equal)

[[ $a -ge $b ]] → 判断 $a 是否大于等于 $b

-lt

小于(less than)

[[ $a -lt $b ]] → 判断 $a 是否小于 $b

-le

小于等于(less or equal)

[[ $a -le $b ]] → 判断 $a 是否小于等于 $b

2. 整数测试实战案例

以下三个案例分别实现 “命令行传参比较”“交互式输入比较”“if 多分支比较”,覆盖整数测试的常见场景。

案例 1:命令行传递参数比较

需求:接收两个命令行参数,先判断参数数量是否为 2,再判断是否为整数,最后比较大小。

#!/bin/bash# 脚本名:a.sh# 1. 判断参数数量是否为 2if [[ $# -ne 2 ]]; thenecho "错误:必须输入两个参数"exit 1 # 非 0 退出码表示执行失败fi# 2. 判断参数是否为整数(利用 expr 计算,非整数会报错)expr $1 + $2 > /dev/null 2>&1 # 重定向错误输出,避免干扰if [[ $? -ne 0 ]]; then # $? 是上一条命令的退出码(0 为真,非 0 为假)echo "错误:输入的参数必须是整数"exit 1fi# 3. 比较两个整数的大小if [[ $1 -gt $2 ]]; thenecho "$1 大于 $2"elif [[ $1 -lt $2 ]]; thenecho "$1 小于 $2"elseecho "$1 等于 $2"fi执行示例:sh a.sh 10 20 → 10 小于 20sh a.sh 20 10 → 20 大于 10sh a.sh 15 15 → 15 等于 15sh a.sh 10 → 错误:必须输入两个参数sh a.sh 10 abc → 错误:输入的参数必须是整数
案例 2:交互式输入参数比较

需求:通过 read 命令让用户交互式输入两个整数,再比较大小。

#!/bin/bash# 脚本名:c.sh# 1. 交互式输入两个参数read -p "请输入要比较的第一个整数:" num1read -p "请输入要比较的第二个整数:" num2# 2. 判断是否为整数expr $num1 + $num2 > /dev/null 2>&1if [[ $? -ne 0 ]]; thenecho "错误:输入的必须是整数"exit 1fi# 3. 比较大小[[ $num1 -gt $num2 ]] && echo "$num1 大于 $num2"[[ $num1 -lt $num2 ]] && echo "$num1 小于 $num2"[[ $num1 -eq $num2 ]] && echo "$num1 等于 $num2"
  • 执行示例:
sh c.sh请输入要比较的第一个整数:5请输入要比较的第二个整数:85 小于 8
案例 3:多分支选择(英雄选择)

需求:让用户选择英雄编号(1-3),根据选择输出对应结果,输入其他编号提示 “选择无效”。

#!/bin/bash# 脚本名:d.sh# 1. 显示英雄列表echo "===== 选择你的英雄 ====="cat <<EOF1. 全民偶像:鹿晗2. 综艺之神:陈赫3. 魔童:邓超EOF# 2. 接收用户输入read -p "请输入英雄编号(1-3):" num# 3. 多分支判断(结合整数测试和逻辑或 `-o`)if [[ $num -eq 1 -o $num -eq 2 -o $num -eq 3 ]]; thenif [[ $num -eq 1 ]]; thenecho "已选择:全民偶像 · 鹿晗!"elif [[ $num -eq 2 ]]; thenecho "已选择:综艺之神 · 陈赫!"elseecho "已选择:魔童 · 邓超!"fielseecho "错误:你选择了无效的英雄编号!"fi
  • 执行示例:
sh d.sh===== 选择你的英雄 =====1. 全民偶像:鹿晗2. 综艺之神:陈赫3. 魔童:邓超请输入英雄编号(1-3):2已选择:综艺之神 · 陈赫!

三、字符测试(字符串比较)

字符测试用于检查字符串的内容等值长度是否为空,需注意字符串需加引号(避免空格或特殊字符导致解析错误)。

1. 字符测试运算符

运算符

含义

示例(判断字符串 $str 或 $str1 与 $str2 的关系)

==

等值比较(内容完全一致)

[[ "$str1" == "$str2" ]] → 判断两个字符串是否相同

!=

不等值比较(内容不同)

[[ "$str1" != "$str2" ]] → 判断两个字符串是否不同

-z

字符串为空(长度为 0)

[[ -z "$str" ]] → 判断 $str 是否为空

-n

字符串非空(长度 > 0)

[[ -n "$str" ]] → 判断 $str 是否非空

2. 字符测试实战案例

案例:用户名验证

需求:让用户输入用户名,判断是否为空、是否为指定用户名(如 admin)。

#!/bin/bash# 脚本名:e.sh# 1. 接收用户名输入read -p "请输入用户名:" username# 2. 判断用户名是否为空if [[ -z "$username" ]]; thenecho "错误:用户名不能为空!"exit 1fi# 3. 判断用户名是否为 adminif [[ "$username" == "admin" ]]; thenecho "欢迎你,管理员 $username!"elseecho "欢迎你,普通用户 $username!"fi
  • 执行示例:
sh e.sh请输入用户名:admin → 欢迎你,管理员 admin!sh e.sh请输入用户名:zhangsan → 欢迎你,普通用户 zhangsan!sh e.sh请输入用户名:(直接回车)→ 错误:用户名不能为空!

四、文件测试(文件 / 目录属性判断)

文件测试是 Shell 脚本中最常用的判断场景,用于检测文件 / 目录的存在性、类型、权限、大小等属性,需使用专用的文件测试运算符。

1. 文件测试运算符分类

根据测试目标,文件测试运算符可分为 6 类,覆盖所有常见文件属性:

(1)存在性测试

运算符

含义

示例

-e

测试文件 / 目录是否存在

[[ -e /tmp/file ]] → 判断 /tmp/file 是否存在

(2)类型测试(存在且为指定类型)

运算符

含义

示例

-f

普通文件(非目录 / 链接)

[[ -f /tmp/file ]] → 判断是否为普通文件

-d

目录

[[ -d /tmp/dir ]] → 判断是否为目录

-L

符号链接文件

[[ -L /tmp/link ]] → 判断是否为软链接

-b

块设备文件(如磁盘 /dev/sda)

[[ -b /dev/sda ]] → 判断是否为块设备

-c

字符设备文件(如键盘 /dev/tty1)

[[ -c /dev/tty1 ]] → 判断是否为字符设备

-S

套接字文件(如 /var/run/mysql.sock)

[[ -S /var/run/mysql.sock ]] → 判断是否为套接字

(3)权限测试(当前用户是否有对应权限)

运算符

含义

示例

-r

读权限

[[ -r /tmp/file ]] → 当前用户是否能读该文件

-w

写权限

[[ -w /tmp/file ]] → 当前用户是否能写该文件

-x

执行权限(文件)/ 进入权限(目录)

[[ -x /tmp/script.sh ]] → 当前用户是否能执行该脚本

(4)特殊权限测试

运算符

含义

示例

-u

拥有 SUID 权限(执行时继承文件所有者权限)

[[ -u /usr/bin/passwd ]] → 判断 passwd 是否有 SUID

-g

拥有 SGID 权限(执行时继承文件所属组权限)

[[ -g /tmp/dir ]] → 判断目录是否有 SGID

-k

拥有 Sticky 权限(目录中仅所有者可删除自己的文件)

[[ -k /tmp ]] → 判断 /tmp 是否有 Sticky 权限

(5)大小与修改测试

运算符

含义

示例

-s

文件非空(大小 > 0)

[[ -s /tmp/file ]] → 判断文件是否有内容

-N

文件自上次读取后是否被修改过

[[ -N /tmp/file ]] → 判断文件是否被修改

(6)双目测试(两个文件的关系)

运算符

含义

示例

-ef

两个文件是否为同一文件(相同 inode)

[[ /tmp/file1 -ef /tmp/file2 ]] → 判断是否为硬链接

-nt

文件 1 是否比文件 2 新(修改时间)

[[ /tmp/file1 -nt /tmp/file2 ]] → file1 比 file2 新?

-ot

文件 1 是否比文件 2 旧(修改时间)

[[ /tmp/file1 -ot /tmp/file2 ]] → file1 比 file2 旧?

2. 文件测试实战案例

需求:先创建一批测试文件 / 目录,再编写脚本检测它们的属性(存在性、类型、特殊权限等)。

步骤 1:创建测试文件 / 目录
#!/bin/bash# 脚本名:test.sh# 创建普通文件touch /tmp/file1 /tmp/file2# 创建目录mkdir /tmp/dir1 /tmp/dir3# 创建符号链接(指向 dir1)ln -s /tmp/dir1 /tmp/dir2# 给 dir3 添加 SGID 权限chmod g+s /tmp/dir3echo "测试文件/目录创建完成!"
步骤 2:编写文件测试脚本
#!/bin/bash# 脚本名:file.sh# 定义测试文件/目录路径file1="/tmp/file1"file2="/tmp/file2"dir1="/tmp/dir1"link2="/tmp/dir2"dir3="/tmp/dir3"file4="/tmp/file4" # 不存在的文件# 1. 测试存在性echo "===== 存在性测试 ====="[[ -e $file1 ]] && echo "$file1 → 存在" || echo "$file1 → 不存在"[[ -e $file4 ]] && echo "$file4 → 存在" || echo "$file4 → 不存在"# 2. 测试文件类型echo -e "\n===== 类型测试 ====="[[ -f $file2 ]] && echo "$file2 → 普通文件" || echo "$file2 → 非普通文件"[[ -d $dir1 ]] && echo "$dir1 → 目录" || echo "$dir1 → 非目录"[[ -L $link2 ]] && echo "$link2 → 符号链接" || echo "$link2 → 非符号链接"# 3. 测试特殊权限(SGID)echo -e "\n===== 特殊权限测试 ====="[[ -g $dir3 ]] && echo "$dir3 → 拥有 SGID 权限" || echo "$dir3 → 无 SGID 权限"# 4. 测试权限(当前用户是否有写权限)echo -e "\n===== 权限测试 ====="[[ -w $file1 ]] && echo "$file1 → 当前用户有写权限" || echo "$file1 → 当前用户无写权限"
步骤 3:执行与输出结果
# 先创建测试文件sh test.sh → 测试文件/目录创建完成!# 执行测试脚本sh file.sh

输出结果:

===== 存在性测试 =====/tmp/file1 → 存在/tmp/file4 → 不存在===== 类型测试 =====/tmp/file2 → 普通文件/tmp/dir1 → 目录/tmp/dir2 → 链接文件===== 特殊权限测试 =====/tmp/dir3 → 拥有 SGID 权限===== 权限测试 =====/tmp/file1 → 当前用户有写权限

五、组合测试(多条件判断)

当需要同时判断多个条件时,需使用组合测试运算符(与、或、非),将多个简单条件组合成复杂逻辑。

1. 组合测试运算符

运算符

逻辑关系

说明

示例(判断 $a>10 且 $a<20)

-a

逻辑与(AND)

所有条件都为真,结果才为真

[[ $a -gt 10 -a $a -lt 20 ]]

&&

逻辑与(AND)

Bash 扩展,功能与 -a 一致,优先级更高

[[ $a -gt 10 && $a -lt 20 ]]

-o

逻辑或(OR)

任意一个条件为真,结果就为真

[[ $a -lt 10 -o $a -gt 20 ]]

`

`

逻辑或(OR)

!

逻辑非(NOT)

条件为真时结果为假,条件为假时结果为真

[[ ! -e /tmp/file ]](判断文件不存在)

2. 组合测试实战案例

案例:年龄合法性判断

需求:让用户输入年龄,判断是否在 “18~60” 之间(合法),否则提示 “年龄不合法”。

#!/bin/bash# 脚本名:age.shread -p "请输入你的年龄:" age# 组合条件:年龄是整数 + 年龄 >=18 + 年龄 <=60# 步骤1:判断是否为整数expr $age + 0 > /dev/null 2>&1if [[ $? -ne 0 ]]; thenecho "错误:年龄必须是整数!"exit 1fi# 步骤2:组合判断年龄范围(18<=age<=60)if [[ $age -ge 18 && $age -le 60 ]]; thenecho "年龄合法(18~60岁)"elseecho "年龄不合法(需在18~60岁之间)"fi
  • 执行示例:
sh age.sh请输入你的年龄:25 → 年龄合法(18~60岁)sh age.sh请输入你的年龄:15 → 年龄不合法(需在18~60岁之间)sh age.sh请输入你的年龄:abc → 错误:年龄必须是整数!

六、if 语句(流程控制核心)

if 语句是 Shell 脚本中最基础的流程控制结构,根据条件的真假执行不同的命令块,分为单分支双分支多分支三种形式。

1. 单分支 if 语句(满足条件才执行)

语法格式
if 条件表达式; then# 条件为真时执行的命令命令1命令2fi # 结束 if 语句(必须闭合)
案例:检查文件是否存在

需求:若 /tmp/file1 存在,输出 “文件已存在”。

#!/bin/bash# 脚本名:test.shfile="/tmp/file1"if [[ -e $file ]]; thenecho "文件已存在:$file"echo "文件大小:$(du -sh $file)" # 额外输出文件大小fi

2. 双分支 if 语句(二选一执行)

语法格式
if 条件表达式; then# 条件为真时执行的命令块命令1else# 条件为假时执行的命令块命令2fi

3. 多分支 if 语句(多选一执行)

语法格式
if 条件1; then# 条件1为真时执行命令1elif 条件2; then # else if 的缩写,可多个# 条件2为真时执行命令2elif 条件3; then# 条件3为真时执行命令3else# 所有条件都为假时执行命令4fi
案例:成绩等级判断

需求:根据输入的分数(0~100),判断等级(A:90~100,B:80~89,C:60~79,D:<60)。

#!/bin/bash# 脚本名:cj.shread -p "请输入你的分数(0~100):" score# 先判断是否为整数且在 0~100 范围内expr $score + 0 > /dev/null 2>&1if [[ $? -ne 0 || $score -lt 0 || $score -gt 100 ]]; thenecho "错误:分数必须是 0~100 之间的整数!"exit 1fi# 多分支判断等级if [[ $score -ge 90 ]]; thenecho "你的等级:A(优秀)"elif [[ $score -ge 80 ]]; thenecho "你的等级:B(良好)"elif [[ $score -ge 60 ]]; thenecho "你的等级:C(及格)"elseecho "你的等级:D(不及格)"fi
  • 执行示例:
sh cj.sh请输入你的分数(0~100):85 → 你的等级:B(良好)sh cj.sh请输入你的分数(0~100):59 → 你的等级:D(不及格)sh cj.sh请输入你的分数(0~100):105 → 错误:分数必须是 0~100 之间的整数!

七、判断逻辑的注意事项

  1. 空格问题:[ ] 或 [[ ]] 前后必须有空格,运算符(如 -eq、==)前后也必须有空格,否则会报语法错误。                                                                                                                            .错误示例:[ $a==$b ](缺少空格);正确示例:[[ $a == $b ]]。
  2. 字符串引号:字符测试时,字符串变量必须加双引号("$str"),避免因字符串为空或含空格导致解析错误。                                                                                                                      错误示例:[[ -z $username ]](空字符串会变成 [[ -z ]],语法错误);正确示例:[[ -z "$username" ]]。
  3. 整数与字符区分:整数测试用 -eq/-gt 等运算符,字符测试用 ==/!= 等运算符,不可混用。  错误示例:[[ "10" -gt "5" ]](字符串用整数运算符,虽可能生效,但不规范);正确示例:[[ 10 -gt 5 ]](整数直接比较)。
  4. 优先级问题:组合测试中,!(非)优先级最高,&&(与)次之,||(或)最低;若有复杂逻辑,建议用 () 包裹(需转义为 \(\) 或用 [[ ]] 自动支持)。                                                    .示例:[[ $age -ge 18 && ($score -ge 60 || $level == "A") ]](先判断分数或等级,再与年龄组合)。
  5. 退出码理解:所有条件测试的结果都通过退出码($?)表示,$?=0 为真,$?!=0 为假;避免直接用 echo $? 输出,应通过 if 或 &&/|| 判断。

总结

Shell 脚本的判断逻辑是流程控制的核心,需掌握以下关键点:

  1. 三类测试:整数测试(比较大小)、字符测试(字符串属性)、文件测试(文件属性),覆盖所有常见判断场景;
  2. 两种格式:推荐使用 [[ 条件 ]] 格式(支持正则和扩展逻辑运算符),避免 [ ] 的兼容性问题;
  3. 三种 if 结构:单分支(满足才执行)、双分支(二选一)、多分支(多选一),根据需求选择合适的结构;
  4. 组合逻辑:用 &&/||/! 实现多条件组合,注意优先级和括号的使用。

通过本文的案例练习,可快速掌握判断逻辑的实际应用,为编写复杂的自动化脚本打下基础。


文章转载自:

http://oAWYP6ch.Lkgqb.cn
http://kzntqjfi.Lkgqb.cn
http://RENOJ18k.Lkgqb.cn
http://BQd8TMBF.Lkgqb.cn
http://C1uh7cht.Lkgqb.cn
http://tjJi5EZF.Lkgqb.cn
http://RgtR1Idj.Lkgqb.cn
http://YgGXHJ67.Lkgqb.cn
http://YgYo9Hvl.Lkgqb.cn
http://N77KBRVI.Lkgqb.cn
http://sY2r7QvQ.Lkgqb.cn
http://xxlwP0qG.Lkgqb.cn
http://uTdhPKu7.Lkgqb.cn
http://viY1CDR2.Lkgqb.cn
http://i0w9QcCm.Lkgqb.cn
http://bNdsKFYr.Lkgqb.cn
http://qN7JCyjS.Lkgqb.cn
http://oKP9ESBd.Lkgqb.cn
http://272MN8Tm.Lkgqb.cn
http://JTzdxviY.Lkgqb.cn
http://wygezOSq.Lkgqb.cn
http://yngTtfMG.Lkgqb.cn
http://fNlccvd4.Lkgqb.cn
http://ROKNXVOR.Lkgqb.cn
http://1kY2At9C.Lkgqb.cn
http://MbcBLhXJ.Lkgqb.cn
http://sGSzQZii.Lkgqb.cn
http://tVJwGYUU.Lkgqb.cn
http://421wt0dw.Lkgqb.cn
http://5QTU94VU.Lkgqb.cn
http://www.dtcms.com/a/375755.html

相关文章:

  • 前端工程化资源预加载
  • Linux-Shell编程正则表达式
  • CentOS7静态IP设置全攻略
  • Kafka面试精讲 Day 12:副本同步与数据一致性
  • [职业竞赛][移动应用]网络请求、JSON 文件读取解析、APP全局变量
  • 2、Python函数设计与字典应用
  • 数据分析与AI丨如何用数据分析找到更优的橡胶配方?
  • Flask 核心基础:从 路由装饰器 到 __name__ 变量 的底层逻辑解析
  • 微服务事务管理利器:Seata 核心原理与实践指南
  • ZYNQ PS 端 UART 接收数据数据帧(初学者友好版)
  • 【ARM-day03】
  • TI-92 Plus计算器:单位换算功能介绍
  • TDengine 选择函数 Max() 用户手册
  • 总结 IO、存储、硬盘、文件系统相关常识
  • MATLAB基于GM(灰色模型)与LSTM(长短期记忆网络)的组合预测方法
  • cnn,vit,mamba是如何解决医疗影像问题的
  • 数据库连接池:性能优化的秘密武器
  • 鸿蒙(HarmonyOS) 历史
  • 华为Ai岗机考20250903完整真题
  • 机器人控制器开发(文章总览)
  • 怎么选适合企业的RPA财务机器人?
  • Vite:Next-Gen Frontend Tooling 的高效之道——从原理到实践的性能革命
  • 常用优化器及其区别
  • 【Ansible】管理变量和事实知识点
  • 2025-09-08升级问题记录:app提示“此应用专为旧版Android打造..”或“此应用与最新版 Android 不兼容”
  • 网络通信的“地址”与“门牌”:详解IP地址与端口号的关系
  • 基于Python的旅游数据分析可视化系统【2026最新】
  • Nginx 优化与防盗链全解析:从性能调优到资源保护
  • 【AI】Tensorflow在jupyterlab中运行要注意的问题
  • (论文速读)从语言模型到通用智能体