type
status
date
slug
tags
summary
category
password
icon
AI 摘要
Bash 脚本编程入门
1. 简介
Bash (Bourne Again SHell) 是 Linux 和 macOS 系统中最常用的 Shell 之一。Bash 脚本允许将一系列命令组合到一个文件中,以自动化任务、简化复杂操作或创建新的工具。
2. 第一个 Bash 脚本
2.1 创建脚本文件
使用文本编辑器(如
nano, vim, gedit, vscode 等)创建一个新文件,通常以 .sh 结尾(例如 hello.sh)。2.2 Shebang
脚本的第一行通常是 "Shebang",它告诉系统使用哪个解释器来执行脚本。对于 Bash 脚本,它是:
或者,如果希望使用环境中的
bash 版本:2.3 添加命令
在 Shebang 下方添加想要执行的命令。最简单的例子是打印一条消息:
2.4 赋予执行权限
创建的脚本文件默认没有执行权限。需要使用
chmod 命令添加:这里的
+x 表示添加执行权限。2.5 执行脚本
有几种方法可以执行脚本:
- 使用相对路径或绝对路径:
- 通过 Bash 解释器: (不需要执行权限)
3. 变量
3.1 定义变量
在 Bash 中,定义变量的语法是
VARIABLE_NAME=value。注意: 等号 = 两边不能有空格。变量名通常使用大写字母。3.2 使用变量
使用美元符号
$ 加上变量名来引用变量的值,例如 $VARIABLE_NAME 或 ${VARIABLE_NAME}。花括号 {} 在变量名与其他字符连接时特别有用,可以避免歧义。3.3 环境变量
脚本可以访问已存在的环境变量,例如
$HOME, $USER, $PATH。4. 用户输入 (read)
read 命令用于从标准输入(通常是键盘)读取用户输入并存入变量。5. 命令行参数
脚本可以接收在执行时传递给它的参数。Bash 提供了一些特殊变量来访问这些参数:
$0: 脚本本身的名称。
$1,$2,$3, ...: 第一个、第二个、第三个...参数。对于超过 9 个的参数,需要使用${10},${11}等。
$#: 传递给脚本的参数总数 (不包括$0)。
$@: 所有参数列表,每个参数被视为独立的字符串("$1" "$2" "$3" ...)。当被双引号包围时 ("$@"),这是最常用的形式。
$*: 所有参数列表,被视为一个单一的字符串("$1c$2c$3...",其中c是 IFS 的第一个字符,默认为空格)。当被双引号包围时 ("$*"),行为与"$@"不同。
$$: 当前脚本的进程 ID (PID)。
$?: 上一个命令的退出状态码。 0 通常表示成功,非 0 值表示失败。
示例 (
args.sh):执行:
输出:
6. 退出状态 ($? 和 exit)
每个命令执行后都会有一个退出状态码,存储在特殊变量
$? 中。- 0: 命令成功执行。
- 非 0 (1 - 255): 命令执行失败。不同的非零值可以表示不同类型的错误。
可以使用
exit 命令显式地设置脚本的退出状态。在脚本执行后,可以在终端中通过
echo $? 查看其最终退出状态。7. 控制流
7.1 条件语句 (if, elif, else)
if 语句基于命令的退出状态来执行代码块。基本语法:
测试条件 (
test 或 [ ] 或 [[ ]])test expression或[ expression ]: 传统的测试方式。注意:[是一个命令,所以它和表达式之间必须有空格,表达式末尾的]之前也必须有空格。
[[ expression ]]: Bash 提供的增强型测试方式,更灵活且不易出错(例如,对变量扩展和单词分割的处理更安全)。推荐使用[[ ]]。
常用测试操作符:
- 字符串比较:
=或==: 相等 (在[[ ]]中==更明确,在[ ]中两者皆可,但=更兼容 POSIX)。!=: 不相等。-z STRING: 字符串长度为零。-n STRING: 字符串长度非零。
- 整数比较:
-eq: 等于 (equal)。-ne: 不等于 (not equal)。-gt: 大于 (greater than)。-ge: 大于或等于 (greater or equal)。-lt: 小于 (less than)。-le: 小于或等于 (less or equal)。
- 文件测试:
-e FILE: 文件存在 (exist)。-f FILE: 文件存在且是普通文件 (file)。-d FILE: 文件存在且是目录 (directory)。-s FILE: 文件存在且大小不为零 (size)。-r FILE: 文件存在且可读 (readable)。-w FILE: 文件存在且可写 (writable)。-x FILE: 文件存在且可执行 (executable)。
- 逻辑操作符:
!: 逻辑非 (NOT)。-a: 逻辑与 (AND) - 仅用于[ ]。-o: 逻辑或 (OR) - 仅用于[ ]。&&: 逻辑与 (AND) - 用于[[ ]]或连接命令。||: 逻辑或 (OR) - 用于[[ ]]或连接命令。
示例:
7.2 case 语句
当需要根据一个变量的多个可能值执行不同操作时,
case 语句比嵌套的 if 更清晰。语法:
模式 pattern1/2/3 可以使用通配符(如
*, ?, [...])。示例:
7.3 for 循环
用于遍历一个列表(字符串、数字、文件名等)。
语法 1: 遍历列表
示例 1:
语法 2: C 风格的
for 循环 (Bash 特有)示例 2:
7.4 while 循环
当给定条件为真 (命令退出状态为 0) 时,重复执行代码块。
语法:
示例:
7.5 until 循环
与
while 相反,当给定条件为假 (命令退出状态非 0) 时,重复执行代码块,直到条件为真。语法:
示例:
7.6 break 和 continue
break: 立即跳出当前循环 (for, while, until)。
continue: 跳过当前循环的剩余部分,直接进入下一次迭代。
8. 函数
函数就是打包一组命令成为一个可重复使用的固定单元。
8.1 定义函数
有两种语法:
注意: 定义函数时,
() 内不写参数。函数内部通过 $1, $2, $#, $@ 等访问传递给它的参数。使用 local 关键字声明的变量只在函数内部可见。8.2 调用函数
直接使用函数名调用:
8.3 获取函数返回值
- 退出状态: 函数执行后,可以通过
$?获取return语句设置的值(或函数中最后一条命令的退出状态),范围是 0-255。
- 输出结果: 如果函数需要返回数据(如字符串或数字),通常的做法是让函数将结果
echo到标准输出,然后在调用处使用命令替换来捕获它。
示例:
9. 命令替换
将一个命令的输出结果作为一个变量的值或用在另一个命令中。
$(command): 推荐 的现代语法,可以嵌套。
`command`: 旧式语法(反引号)。不推荐,可读性差,不易嵌套。
10. 算术运算
Bash 提供了几种执行整数算术运算的方法:
$((expression)): 推荐 的方式。支持 C 风格的操作符 (+, , ,/,%(取模),*(幂),++,-, 等)。
let expression: 类似$(( )),直接修改变量。
expr expression: 旧式命令,操作符和操作数必须用空格隔开,对特殊字符需要转义(如 写成\\*)。不推荐。
注意: Bash 内建的算术运算只支持整数。对于浮点数运算,需要使用外部工具如
bc。11. 引用 (Quoting)
引用用于控制 Shell 如何解释特殊字符。
- 双引号
": - 保留大部分特殊字符的字面意义 (如空格)。
- 允许变量替换 (
$var)、命令替换 ($(cmd)) 和算术替换 ($((expr)))。 - 是最常用的引用方式。
- 单引号
': - 禁止所有替换。所有字符都按字面意义处理。
- 用于需要精确包含特殊字符(如
$、、\\)的场景。
- 反斜杠
\\: - 转义紧随其后的单个字符,使其失去特殊含义。
12. 调试 Bash 脚本
bash -x script.sh: 执行脚本并打印出每个执行的命令及其参数(前面有+符号)。非常有用!
set -x/set +x: 在脚本内部的特定区域开启/关闭命令追踪。
set -e: 当任何命令以非零状态退出时,立即退出脚本。有助于捕获意外错误。
set -u: 当尝试使用未定义的变量时,将其视为错误并退出脚本。
echo调试: 在关键点插入echo语句打印变量值或执行流程标记。
13. 后续学习
以上为 Bash 脚本的基础知识,包括变量、输入输出、控制流、函数、参数处理等。
下一步可以探索:
- 文本处理工具:
grep,sed,awk
- 文件和目录操作:
find,cp,mv,rm,mkdir,tar
- 进程管理:
ps,kill,bg,fg
- 数组 (Bash Arrays)
- 更高级的
[[ ]]测试条件
- 错误处理和日志记录
- 编写更健壮、可移植的脚本