精通 Bash 条件表达式(Conditional Expressions):文件、字符串、算术与退出状态检测全指南
【免费下载链接】introduction-to-bash-scriptingFree Introduction to Bash Scripting eBook项目地址: https://gitcode.com/GitHub_Trending/in/introduction-to-bash-scripting
Bash 条件表达式是编写一切可靠脚本的基石:无论是判断文件是否存在、比较字符串与数字,还是检查上一条命令是否成功,都离不开[[ ]]与[ ]这两组命令。本文基于开源电子书《Introduction to Bash Scripting》中 法语版第 9 章 与 英文版第 9 章 的内容,系统梳理 Bash 中最常用的条件表达式清单,并补充变量展开、引号、通配符匹配等实战陷阱,帮助你读完即可在脚本中直接套用。
在计算机科学中,条件语句(conditional statements)、条件表达式(conditional expressions)与条件构造(conditional constructs)是编程语言的核心特性:它们根据开发者指定的布尔条件(true或false)执行不同的计算或动作。在 Bash 中,条件表达式由[[复合命令(compound command)与[内建命令(built-in command)提供,用于测试文件属性以及执行字符串比较与算术比较。
一、理解[[与[的区别
在深入表达式清单之前,先明确两处使用前提:
[[ ... ]]是 Bash 的复合命令(compound command),是关键字而非普通命令,支持模式匹配、逻辑运算符&&/||、以及==/!=两侧的 glob 通配符展开,是 Bash 脚本中的首选写法;[ ... ]是等效于test的内建命令,属于 POSIX 标准写法,可移植性更强,但它对变量值中的空格敏感(要求严格引号),也不支持模式匹配。
正如英文原版章节所指出的:当与[[一起使用时,==会执行模式匹配;若要完全符合 POSIX 规范,则应使用=配合test/[命令。
二、文件表达式(File Expressions):检测文件与目录属性
文件表达式用于测试某个路径是否存在、类型以及权限属性。以下是最常用的清单,直接复制即可使用(${fichier}为存放路径的变量):
| 表达式 | 含义 |
|---|---|
[[ -a ${fichier} ]] | 文件存在即真 |
[[ -b ${fichier} ]] | 文件存在且为块特殊文件(block special file,如磁盘设备) |
[[ -c ${fichier} ]] | 文件存在且为字符特殊文件(character special file,如终端设备) |
[[ -d ${fichier} ]] | 文件存在且为目录 |
[[ -e ${fichier} ]] | 文件存在即真(-a的历史别名) |
[[ -f ${fichier} ]] | 文件存在且为普通文件 |
[[ -h ${fichier} ]] | 文件存在且为符号链接(同-L) |
[[ -r ${fichier} ]] | 文件存在且可读 |
[[ -s ${fichier} ]] | 文件存在且大小大于 0 |
[[ -w ${fichier} ]] | 文件存在且可写 |
[[ -x ${fichier} ]] | 文件存在且可执行 |
[[ -L ${fichier} ]] | 文件存在且为符号链接(同-h) |
典型场景:脚本启动时校验配置文件是否存在、目录是否可写、可执行文件是否有执行权限。例如:
#!/bin/bash config="/etc/myapp/config.ini" if [[ ! -f "${config}" ]]; then echo "配置文件不存在: ${config}" exit 1 fi注意!可对整个表达式取反([[ ! -d ${dir} ]]表示"目录不存在"),这是条件表达式在实战中最常用的变形之一。
三、字符串表达式(String Expressions):判空、判等与排序比较
字符串表达式用于检测变量是否已赋值、字符串长度是否为零,以及字符串之间的相等与字典序关系:
| 表达式 | 含义 |
|---|---|
[[ -v ${varname} ]] | 变量varname已被赋值(存在) |
[[ -z ${string} ]] | 字符串长度为 0 |
[[ -n ${string} ]] | 字符串长度不为 0 |
[[ ${string1} == ${string2} ]] | 字符串相等 |
[[ ${string1} != ${string2} ]] | 字符串不相等 |
[[ ${string1} < ${string2} ]] | string1在字母序上先于string2 |
[[ ${string1} > ${string2} ]] | string1在字母序上后于string2 |
这里有三个高频踩坑点,值得单独说明:
-v接收的是变量名而非值:英文原版章节特别标注——-v操作符期望传入变量名(varname),如果错误地传入${varname}(展开后的值),表达式将恒为假。正确写法是[[ -v varname ]]。==右侧默认是 glob 模式:在[[ ]]中,==和!=的右侧除非被引号包裹,否则会被当作通配符模式处理。例如[[ $name == *.log ]]会匹配所有以.log结尾的字符串。如果你要的是精确字符串比较,务必给右侧加引号:[[ ${string1} == "${string2}" ]]。这个规则同样适用于!=。<与>需要转义:在[ ](test 命令)中使用\<和\>,因为裸的</>会被 shell 当作重定向符;在[[ ]]中则无需转义,如清单所示。
-z判空是本书后续条件语句章节中最常用的表达式——用户输入校验几乎都从它开始。
四、算术运算符(Arithmetic Operators):整数比较
当需要比较两个整数(可为正数或负数)时,使用以下运算符,切勿与字符串的=/==混淆:
| 表达式 | 含义 |
|---|---|
[[ ${arg1} -eq ${arg2} ]] | arg1等于arg2 |
[[ ${arg1} -ne ${arg2} ]] | arg1不等于arg2 |
[[ ${arg1} -lt ${arg2} ]] | arg1小于arg2 |
[[ ${arg1} -le ${arg2} ]] | arg1小于或等于arg2 |
[[ ${arg1} -gt ${arg2} ]] | arg1大于arg2 |
[[ ${arg1} -ge ${arg2} ]] | arg1大于或等于arg2 |
需要留意的是,这些运算符只适用于整数(包括负整数),不能直接用于浮点数比较;浮点数比较需要借助bc或awk等外部工具。另外,在[[ ]]的算术比较中,变量可以省略$前缀(如[[ num -gt 10 ]]),但为保持清晰一致,本书示例统一使用${arg1}形式。
五、组合条件:AND 与 OR
与其他编程语言一样,Bash 支持用逻辑运算符组合多个测试条件:
[[ test_case_1 ]] && [[ test_case_2 ]] # 逻辑与(AND):两者皆真才为真 [[ test_case_1 ]] || [[ test_case_2 ]] # 逻辑或(OR):任一为真即为真注意这里的&&与||位于两个[[ ]]之间,它们同时也是 shell 层面的命令连接符,具有短路求值语义:&&左侧为假时右侧不再执行,||左侧为真时右侧不再执行。这一特性在后续章节的 if 示例中被大量使用,例如同时校验"用户名不是 admin"与"当前用户不是 root"的多条件防护逻辑。
六、退出状态运算符(Exit Status Operators):检查命令成败
每个 Bash 命令执行后都会返回一个退出状态码(exit status),存放在特殊变量$?中:0表示成功,非零表示出错。可以用算术运算符把它包装成条件表达式:
[[ $? -eq 0 ]] # 上一条命令成功且无错误时返回真 [[ $? -gt 0 ]] # 上一条命令失败或出错时返回真更惯用的写法是直接利用命令本身的退出状态作为 if 条件(if command; then ...),因为if天然接受命令的退出码;[[ $? -eq 0 ]]这种显式写法更适合在需要把状态码"翻译"成条件表达式的场景中使用。注意$?非常"易失"——任何一条中间命令(包括赋值、echo)都会覆盖它的值,因此应尽快消费。
七、从表达式到条件构造:在脚本中实际使用
本章是纯"表达式清单",而它们真正的用武之地在下一章《Bash 条件语句》中,那里会用if、if-else、elif和case将这些表达式组装成完整逻辑。一个最小示例提前预览其用法:
#!/bin/bash read -p "Quel est votre nom ? " nom if [[ -z ${nom} ]]; then echo "Veuillez entrer votre nom !" else echo "Salut ${nom}" fi[[ -z ${nom} ]]正是本章的字符串判空表达式:当用户输入为空时进入提示分支,否则进入问候分支。本书章节的编排顺序(变量 → 用户输入 → 数组 → 条件表达式 → 条件语句 → 循环 → 函数)也印证了这一点:条件表达式是承接输入处理、通向流程控制的关键一环。
八、仓库中的质量保障:shellcheck 验证每个代码块
值得一提的工程实践是,本仓库提供了 scripts/shellcheck-ebook.sh:它会自动抽取英文版电子书所有 markdown 文件中的bash代码块,逐个写入临时文件并运行 shellcheck 进行静态检查,退出码0表示全部通过、1表示存在告警。脚本还通过EXCLUDE变量豁免了若干"教学场景故意为之"的告警码,例如:
SC2034/SC2154:变量看似未使用或未赋值(片段中定义的变量供后续片段使用);SC2078:test_case_1这类占位符导致的常量表达式;SC2043/SC2211:刻意演示的反例代码块与 crontab 语法行。
这意味着你在本书中学到的每一个表达式写法,都经过 shellcheck 以 warning 级别以上的严格度校验,可以直接放心复制到自己的脚本中。整个电子书本身通过 Ibis 工具链(PHP 编写的 Markdown 电子书生成器)构建,并已产出 PDF 与 EPUB 成品(见 ebook/en/export 目录)。
九、小结与建议
条件表达式是 Bash 脚本判断力的来源,建议按以下方式巩固:
- 把本文的文件、字符串、算术三张清单当作速查表,需要时回来查阅,无需死记硬背(原书也如此建议);
- 牢记三个易错点:
-v传变量名、==右侧加引号做精确比较、-z/-n配合用户输入校验; - 继续阅读《Bash 条件语句》学习
if/elif/case的组合用法,并参考本书英文原版章节获取更多补充说明(如-v与模式匹配的注意事项)。
掌握这些表达式后,你将能够写出对文件、用户输入、数值与命令结果做出正确分支判断的健壮脚本,这也是迈向自动化 SysOps/DevOps 任务的第一步。
【免费下载链接】introduction-to-bash-scriptingFree Introduction to Bash Scripting eBook项目地址: https://gitcode.com/GitHub_Trending/in/introduction-to-bash-scripting
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考