Skip to content

Bash Shell:基础对象与机制 ​

解释器、引用、变量与退出状态 ​

Bash / Zsh 的管理用途是把命令组合成可检查的任务。先识别解释器,再理解引用、展开、重定向和退出状态;不能把 Bash 专有语法写进声称兼容 /bin/sh 的脚本。

解释器与系统工具边界 ​

Bash Shell 解释器负责解析语法,grep、sort 等外部程序负责各自的数据处理。Linux 和 macOS 可以运行不同 Shell;Windows 的 Git Bash、WSL 与原生 PowerShell 也不是同一环境。准备阶段只确认已有解释器及其版本,教学固定 Bash5.2,不安装工具。脚本带 shebang 仍可能被错误地用 sh script 忽略。

命令、参数与引用 ​

Bash Shell 引用控制一个值传几个参数。双引号保留变量展开但避免常规拆词与文件名展开,单引号保留字面内容;printf "%s\n" "$value" 让数据不是格式串。变量赋值的等号两侧不能加空格。命令名、选项与数据需分开,含空格路径不能靠反斜杠替换一切输入。

文本输入与协议 ​

Bash Shell 文本输入必须先约定编码、分隔符与记录结构。换行分隔不能表示文件名中的换行,普通 for x in $(cat file) 会拆词,不适合可靠文件列表。本文示例处理受限的 ASCII 标识符行,明确拒绝空格、CR 与斜杠,不冒称任意文件名处理器。通用路径应选 NUL 分隔或对象接口。

变量与子进程 ​

Bash Shell 环境变量通过 export 传给后续子进程,子进程不能直接改父进程环境。source 在当前解释器执行文件,会影响当前变量、目录和选项,不能当作普通运行命令。不要为一次任务 source 未审查的远程文件;本例作为独立脚本调用,不污染读者会话。

练习与参考解答 ​

题目:在Bash默认IFS、开启glob的空目录中,value为字面a b*;比较printf使用固定格式%s和未引用$value、双引号"$value"时的参数个数。随后目录新增b1、b2,未引用结果会怎样?

参考解答:空目录时未引用展开先拆成a与b*,未匹配glob默认保留字面,因而是两个数据参数;双引号保留整个a b*,始终只有一个数据参数。新增b1、b2后,未引用的b*再展开为两文件名,总共三个数据参数a、b1、b2。这里固定假设未启用nullglob/failglob;Zsh默认不按Bash方式拆词,不能直接复用结论。

核对资料 ​

展开、管道、子 shell 与信号 ​

先明确Bash 5.2、稳定普通输入文件与 ASCII 行协议,再对照配套示例理解引用后的参数、stdout/stderr 和退出状态。

教学版本族:Bash 5.2 语义,Zsh 5.9 对比;不假设 macOS 自带 Bash 满足 5.2,不把 /bin/sh 当作 Bash。核对日期2026-10-17,不称为2026最新版。示例未执行,配置与命令需按目标环境验收。

展开顺序与数组 ​

Bash Shell 展开中未引用参数可能经历拆词和 glob。保存多参数用数组,并用 "${args[@]}" 传递每个元素;拼成一个命令字符串再 eval 会重新解析为代码。命令替换会去掉末尾换行,因此不是无损文本容器。参考例将输入行直接作为 printf 数据,不把内容作为命令名。

管道、子 Shell 与状态 ​

Bash Shell 管道连接的是字节流;默认状态来自最后一条命令,开启 pipefail 后由最右侧非零状态决定。管道里的 while 循环通常在子 Shell 中修改变量,循环后父 Shell 的计数未必改变。这里用输入重定向给 while,避免依赖 lastpipe 选项。文本成功输出也不能替代检查退出状态。

退出码与 errexit 边界 ​

Bash Shell 退出码 0 约定成功,非零要按程序契约解释。set -e 在条件、逻辑列表和函数调用上下文有例外,不是异常处理器;trap 也不能处理 SIGKILL。对于关键读取和输出使用显式 if/返回值。本例先完整校验再输出,避免读到第三行才失败时留下貌似成功的前两行。

Bash 与 Zsh 的差异 ​

Bash Shell 与 Zsh 默认语义不同:Zsh 未引用标量通常不做 Bash 式拆词,未匹配 glob 默认可报 nomatch;Bash 通常保留模式字面,除非启用 failglob/nullglob。Zsh 原生数组一般从1开始,Bash从0开始。不能因为交互式 Zsh 能执行某一行,就把 Bash 数组脚本标成两者通用。

练习与参考解答 ​

题目:假设Bash默认lastpipe关闭:count=0后通过printf输出两行并管道送入while read循环,每轮count加1。管道结束后父Shell的count是多少?若改成while循环以输入重定向读同样两行呢?

参考解答:管道中的while通常在子Shell运行,父Shell的count仍为0;子Shell内临时达到2不回写父变量。改成在当前Shell执行while并从文件输入重定向,两次递增作用于父Shell变量,结束后为2。export不解决子进程回写问题,pipefail只改变管道状态汇总,也不改变变量作用域。

核对资料 ​

本节沿用本页资料与示例入口。

继续阅读