外观
Bash 笔记
约 1855 字大约 6 分钟
2025-08-16
一、Bash 简介
1.1 什么是 Bash?
Bash(Bourne-Again SHell)是 Linux 和 macOS 系统中默认的命令行解释器(Shell),是 Bourne Shell 的增强版。它是一个强大的命令行工具,用于与操作系统交互、执行命令和编写脚本。
1.2 Bash 的核心特点
- 命令解释器:执行用户输入的命令
- 脚本语言:支持编写自动化脚本
- 可编程性:支持变量、条件、循环等编程结构
- 高度可定制:可通过配置文件和别名定制环境
- 管道与重定向:强大的数据流处理能力
1.3 常见 Shell 类型
| Shell | 路径 | 特点 |
|---|---|---|
| Bash | /bin/bash | 最常用,功能丰富,Linux 默认 |
| Sh | /bin/sh | 标准 Shell,兼容性好 |
| Zsh | /bin/zsh | 功能强大,自动补全优秀 |
| Ksh | /bin/ksh | Korn Shell,兼容性好 |
二、基础概念
2.1 Shebang 与脚本创建
Shebang:脚本文件的第一行,指定解释器路径
#!/bin/bash
# 或更推荐的写法
#!/usr/bin/env bash创建并执行脚本:
# 创建脚本
echo '#!/bin/bash' > hello.sh
echo 'echo "Hello, World!"' >> hello.sh
# 赋予执行权限
chmod +x hello.sh
# 执行脚本
./hello.sh2.2 注释
# 单行注释
:<<EOF
多行注释
可以跨越多行
EOF2.3 变量
变量命名规则:
- 只能使用英文字母、数字和下划线
- 首字符不能是数字
- 不能使用空格和标点符号
- 不能使用 Bash 关键字
变量操作:
# 声明变量(注意:等号两侧不能有空格)
name="John"
age=30
# 访问变量
echo $name
echo ${age} # 推荐使用花括号形式
# 只读变量
readonly PI=3.14
# PI=3.14159 # 会报错:read-only variable
# 删除变量
unset name
# 特殊变量
echo "脚本名称: $0"
echo "第一个参数: $1"
echo "所有参数: $@"
echo "参数个数: $#"
echo "上一个命令的退出状态: $?"
echo "当前脚本的进程ID: $$"三、数据类型与操作
3.1 字符串操作
字符串定义:
str1="Hello"
str2='World'
str3="Today is $(date)" # 命令替换
str4="1 + 1 = $((1+1))" # 算术替换字符串操作:
# 获取长度
echo ${#str1}
# 子字符串
echo ${str1:1:3} # 从索引1开始取3个字符
# 替换
echo ${str1/ell/ELL} # 替换第一个匹配
echo ${str1//l/1} # 替换所有匹配
# 大小写转换
echo ${str1^^} # 转大写
echo ${str1,,} # 转小写3.2 数组
数组操作:
# 创建数组
colors=("red" "green" "blue")
nums=([0]=1 [1]=2 [2]=3)
files=(*.txt) # 使用通配符
# 访问元素
echo ${colors[0]} # 第一个元素
echo ${colors[@]} # 所有元素
echo ${!colors[@]} # 所有索引
echo ${#colors[@]} # 数组长度
# 添加元素
colors+=("yellow")
# 删除元素
unset colors[2]四、控制结构
4.1 条件判断
test 命令:
# 文件测试
[ -f file.txt ] # 检查是否为普通文件
[ -d directory ] # 检查是否为目录
[ -e file ] # 检查文件是否存在
# 字符串测试
[ -z "$str" ] # 检查字符串是否为空
[ -n "$str" ] # 检查字符串是否非空
[ "$str1" = "$str2" ] # 检查字符串是否相等
# 数值测试
[ "$a" -eq "$b" ] # 等于
[ "$a" -ne "$b" ] # 不等于
[ "$a" -gt "$b" ] # 大于
[ "$a" -lt "$b" ] # 小于if 语句:
if [ "$age" -gt 18 ]; then
echo "Adult"
elif [ "$age" -gt 13 ]; then
echo "Teenager"
else
echo "Child"
ficase 语句:
case $1 in
start)
echo "Starting service"
;;
stop)
echo "Stopping service"
;;
restart)
echo "Restarting service"
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac4.2 循环
for 循环:
# 列表循环
for i in 1 2 3 4 5; do
echo "Number: $i"
done
# C 风格循环
for ((i=0; i<5; i++)); do
echo "Count: $i"
done
# 遍历数组
for color in "${colors[@]}"; do
echo "Color: $color"
donewhile 循环:
# 基本用法
count=1
while [ $count -le 5 ]; do
echo "Count: $count"
((count++))
done
# 读取文件
while IFS= read -r line; do
echo "Line: $line"
done < file.txtuntil 循环:
count=1
until [ $count -gt 5 ]; do
echo "Count: $count"
((count++))
done五、函数
5.1 函数定义与调用
# 定义函数
greet() {
local name=$1 # 局部变量
echo "Hello, $name!"
}
# 调用函数
greet "John"
# 带返回值的函数
add() {
local sum=$(( $1 + $2 ))
return $sum # 注意:返回值范围是0-255
}
add 5 7
echo "Exit status: $?" # 获取返回值5.2 函数最佳实践
- 使用
local关键字声明局部变量 - 函数名应具有描述性
- 为函数添加注释说明用途和参数
- 检查参数数量和有效性
# 带参数检查的函数
validate_input() {
if [ $# -ne 2 ]; then
echo "Error: Two arguments required" >&2
return 1
fi
# 函数逻辑
}六、文件与 I/O 操作
6.1 文件重定向
| 重定向 | 说明 | 示例 |
|---|---|---|
> | 输出重定向(覆盖) | echo "text" > file.txt |
>> | 输出重定向(追加) | echo "text" >> file.txt |
< | 输入重定向 | sort < input.txt |
2> | 错误重定向 | command 2> error.log |
&> | 标准输出和错误重定向 | command &> output.log |
| ` | ` | 管道 |
Here 文档:
cat << EOF
This is a multi-line
string with variables: $name
EOF6.2 常用文件操作命令
# 读取文件
cat file.txt
head -n 5 file.txt # 前5行
tail -n 5 file.txt # 后5行
# 搜索文件
grep "pattern" file.txt
find /path -name "*.txt"
# 文件比较
diff file1.txt file2.txt
# 文件权限
chmod 755 script.sh
chown user:group file.txt七、常用命令与工具
7.1 文本处理工具
# awk - 文本处理语言
awk '{print $1}' file.txt # 打印第一列
# sed - 流编辑器
sed 's/old/new/g' file.txt # 替换文本
# cut - 提取字段
cut -d',' -f1,3 file.csv # 提取CSV文件的第1和第3列
# sort - 排序
sort file.txt
sort -n numbers.txt # 数值排序
# uniq - 去重
sort file.txt | uniq7.2 进程管理
# 查看进程
ps aux
top
# 终止进程
kill PID
kill -9 PID # 强制终止
# 后台运行
command &
jobs # 查看后台任务
fg %1 # 将后台任务转到前台7.3 系统信息
# 系统信息
uname -a
df -h # 磁盘空间
free -h # 内存使用八、调试与错误处理
8.1 脚本调试
调试选项:
#!/bin/bash
set -e # 任何命令失败时退出
set -x # 打印执行的每条命令
set -u # 访问未定义变量时报错
set -o pipefail # 管道中任何命令失败时退出命令行调试:
bash -x script.sh # 执行并显示命令
bash -n script.sh # 仅检查语法8.2 错误处理
# 检查命令是否成功
if ! command; then
echo "Command failed" >&2
exit 1
fi
# trap 捕获信号
cleanup() {
echo "Cleaning up..."
rm -f temp.*
}
trap cleanup EXIT # 脚本退出时执行九、最佳实践
9.1 脚本编写规范
- Shebang:总是以
#!/usr/bin/env bash开头 - 安全设置:在脚本开头添加
set -euo pipefail - 变量引用:总是使用双引号引用变量
"$var" - 错误处理:检查重要命令的返回值
- 注释:为复杂逻辑添加清晰的注释
- 函数化:将逻辑封装为函数,提高可读性
- 参数验证:检查脚本参数是否有效
9.2 常见陷阱与解决方案
陷阱1:变量未加引号
# 错误
if [ $name = "John" ]; then
# 正确
if [ "$name" = "John" ]; then陷阱2:空变量导致命令参数错误
# 错误
rm -rf $directory/*
# 正确
rm -rf "$directory"/*陷阱3:文件名包含空格
# 错误
for file in $(ls); do
# 正确
while IFS= read -r file; do
# 处理文件
done < <(find . -type f)十、实用技巧
10.1 参数扩展
# 默认值
echo ${var:-default} # 变量为空时使用默认值
# 错误提示
echo ${var:?变量未设置} # 变量为空时报错
# 替换
echo ${var/pattern/replacement} # 替换第一个匹配
echo ${var//pattern/replacement} # 替换所有匹配10.2 算术运算
# 整数运算
echo $(( 5 + 3 * 2 ))
echo $(( 10 / 3 )) # 结果为3
# 位运算
echo $(( 5 & 3 )) # 按位与
echo $(( 5 | 3 )) # 按位或
# 三元运算
result=$(( a > b ? a : b ))10.3 命令替换
# 反引号方式(不推荐)
files=`ls *.txt`
# $() 方式(推荐)
files=$(ls *.txt)
current_date=$(date +%Y-%m-%d)