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)
- 更高级的
[[ ]]
测试条件
- 错误处理和日志记录
- 编写更健壮、可移植的脚本