跳到主要内容

Shell 脚本速查表

本页面汇总了 Shell 脚本编程最常用的语法和命令,方便快速查阅。

脚本结构

#!/bin/bash
# Shebang:指定解释器

set -e # 命令失败时退出
set -u # 使用未定义变量时报错
set -x # 打印执行的命令
set -o pipefail # 管道中任何命令失败时返回失败

# 或合并写法
set -euo pipefail

变量

定义和使用

name="John"           # 定义变量(等号两边不能有空格)
echo $name # 使用变量
echo ${name} # 推荐使用花括号
echo "${name}'s home" # 字符串中使用

readonly PI=3.14 # 只读变量
unset name # 删除变量

特殊变量

变量含义
$0脚本名称
$1-$9第 1-9 个参数
${10}第 10 个及之后的参数
$#参数个数
$@所有参数(独立字符串)
$*所有参数(单个字符串)
$?上一个命令的退出状态
$$当前进程 PID
$!最后一个后台进程 PID
$RANDOM随机数 0-32767
$LINENO当前行号
$BASH_VERSIONBash 版本
$FUNCNAME当前函数名

参数扩展

${var:-default}       # var 未定义则使用 default
${var:=default} # var 未定义则赋值并使用
${var:+alternative} # var 已定义则使用 alternative
${var:?error} # var 未定义则打印错误并退出
${#var} # 字符串长度
${var:start:length} # 子字符串
${var#pattern} # 删除最短前缀匹配
${var##pattern} # 删除最长前缀匹配
${var%pattern} # 删除最短后缀匹配
${var%%pattern} # 删除最长后缀匹配
${var/old/new} # 替换第一个匹配
${var//old/new} # 替换所有匹配
${var^} # 首字母大写
${var^^} # 全部大写
${var,} # 首字母小写
${var,,} # 全部小写

数组

索引数组

arr=(a b c d)         # 创建数组
arr[4]=e # 添加元素
arr+=(f g) # 追加元素

echo ${arr[0]} # 访问元素
echo ${arr[@]} # 所有元素
echo ${#arr[@]} # 数组长度
echo ${!arr[@]} # 所有索引

unset arr[1] # 删除元素
unset arr # 删除数组

关联数组

declare -A dict
dict=([name]="John" [age]=25)

echo ${dict[name]} # 访问元素
echo ${!dict[@]} # 所有键
echo ${dict[@]} # 所有值

遍历数组

# 遍历元素
for item in "${arr[@]}"; do
echo "$item"
done

# 遍历索引
for i in "${!arr[@]}"; do
echo "$i: ${arr[$i]}"
done

字符串

str="Hello, World!"

# 长度
${#str} # 13

# 子字符串
${str:0:5} # Hello
${str:7} # World!
${str: -6} # World!(注意空格)

# 替换
${str/World/Shell} # Hello, Shell!
${str//o/0} # Hell0, W0rld!

# 大小写
${str^^} # HELLO, WORLD!
${str,,} # hello, world!

# 删除前后缀
path="/usr/local/bin/script.sh"
${path##*/} # script.sh(文件名)
${path%/*} # /usr/local/bin(目录名)

条件判断

文件测试

运算符含义
-e存在
-f是普通文件
-d是目录
-r可读
-w可写
-x可执行
-s非空
-L是符号链接
-nt比另一个新
-ot比另一个旧

数值比较

运算符含义
-eq等于
-ne不等于
-gt大于
-ge大于等于
-lt小于
-le小于等于

字符串比较

运算符含义
=相等
!=不相等
-z长度为 0
-n长度不为 0

条件语法

# if 语句
if [[ condition ]]; then
commands
elif [[ condition ]]; then
commands
else
commands
fi

# [ ] 和 [[ ]] 和 (())
[ "$a" -eq "$b" ] # 基本测试
[[ $a -eq $b ]] # 扩展测试(推荐)
(( a == b )) # 算术测试

# 逻辑运算
[[ -f "$f" && -r "$f" ]] # 与
[[ -f "$f" || -d "$f" ]] # 或
[[ ! -f "$f" ]] # 非

# 正则匹配
[[ "$str" =~ ^[0-9]+$ ]] # 匹配纯数字

循环

for 循环

# 遍历列表
for item in a b c; do
echo $item
done

# 遍历范围
for i in {1..5}; do
echo $i
done

# C 风格
for ((i=0; i<5; i++)); do
echo $i
done

# 遍历数组
for item in "${arr[@]}"; do
echo $item
done

# 遍历文件
for file in *.txt; do
echo "$file"
done

while 循环

while [[ condition ]]; do
commands
done

# 读取文件
while IFS= read -r line; do
echo "$line"
done < file.txt

# 无限循环
while true; do
commands
done

until 循环

until [[ condition ]]; do
commands
done

循环控制

break       # 跳出循环
break 2 # 跳出 2 层循环
continue # 跳过当前迭代

case 语句

case $var in
pattern1)
commands
;;
pattern2|pattern3)
commands
;;
[a-z])
echo "小写字母"
;;
*)
default commands
;;
esac

函数

# 定义函数
func() {
local var="local" # 局部变量
echo "Hello, $1!"
return 0 # 返回状态码
}

# 调用
func "World"

# 获取返回值
result=$(func "World") # 捕获输出
status=$? # 获取退出状态

输入输出

重定向

cmd > file       # 输出到文件(覆盖)
cmd >> file # 输出到文件(追加)
cmd 2> file # 错误输出到文件
cmd &> file # 所有输出到文件
cmd < file # 从文件输入
cmd1 | cmd2 # 管道
cmd <<< "string" # Here String

Here Document

cat << EOF
Line 1
Line 2
$variable # 会展开
EOF

cat << 'EOF'
$variable # 不会展开
EOF

读取输入

read var                 # 读取一行
read -p "Prompt: " var # 带提示
read -s var # 静默输入(密码)
read -t 5 var # 5 秒超时
read -a arr # 读取到数组
IFS=',' read -a arr # 指定分隔符

算术运算

# 算术扩展
$((a + b)) # 加
$((a - b)) # 减
$((a * b)) # 乘
$((a / b)) # 除
$((a % b)) # 取模
$((a ** b)) # 幂

# 自增/自减
((i++))
((i--))

# 复合赋值
((i += 5))

# 比较运算符
((a == b)) # 等于
((a != b)) # 不等于
((a > b)) # 大于
((a < b)) # 小于

# 位运算
((a & b)) # 按位与
((a | b)) # 按位或
((a ^ b)) # 按位异或
((a << n)) # 左移
((a >> n)) # 右移

命令行参数解析

位置参数

$0              # 脚本名称
$1, $2, ... # 位置参数
$# # 参数个数
$@ # 所有参数(独立)
$* # 所有参数(合并)

shift # 参数左移
shift 2 # 左移 2 位

getopts

while getopts "a:b:c" opt; do
case $opt in
a) arg_a="$OPTARG" ;;
b) arg_b="$OPTARG" ;;
c) flag_c=1 ;;
\?) echo "无效选项: -$OPTARG" >&2; exit 1 ;;
:) echo "选项 -$OPTARG 需要参数" >&2; exit 1 ;;
esac
done
shift $((OPTIND-1))

变量说明

变量含义
OPTIND下一个参数索引
OPTARG当前选项的参数值
OPTERR是否显示错误(0 禁用)

长选项(手动解析)

while [[ $# -gt 0 ]]; do
case $1 in
-f|--file)
file="$2"
shift 2
;;
-v|--verbose)
verbose=1
shift
;;
--)
shift
break
;;
*)
echo "未知选项: $1"
exit 1
;;
esac
done

文本处理

grep

grep "pattern" file        # 搜索
grep -i "pattern" file # 忽略大小写
grep -v "pattern" file # 反向匹配
grep -r "pattern" dir # 递归搜索
grep -n "pattern" file # 显示行号
grep -c "pattern" file # 统计匹配数
grep -l "pattern" *.txt # 只显示文件名
grep -E "regex" file # 扩展正则
grep -o "pattern" file # 只显示匹配部分
grep -A 3 "pattern" file # 显示匹配行及后 3 行
grep -B 3 "pattern" file # 显示匹配行及前 3 行
grep -C 3 "pattern" file # 显示匹配行及前后各 3 行

sed

sed 's/old/new/' file          # 替换第一个
sed 's/old/new/g' file # 替换所有
sed -i 's/old/new/g' file # 直接修改文件
sed '3d' file # 删除第 3 行
sed '/pattern/d' file # 删除匹配行
sed -n '5,10p' file # 打印第 5-10 行
sed 's/^/prefix: /' file # 行首添加
sed 's/$/ :suffix/' file # 行尾添加

awk

awk '{print $1}' file          # 打印第 1 列
awk -F: '{print $1}' file # 指定分隔符
awk '$3 > 100' file # 条件过滤
awk '{sum+=$1} END{print sum}' # 求和
awk 'NR==5' file # 打印第 5 行
awk 'END{print NR}' file # 统计行数
awk '{print NR, $0}' file # 带行号输出
awk '{count[$1]++} END{for(k in count) print k, count[k]}' file # 统计频率

cut

cut -d: -f1 file               # 按 : 分隔取第 1 列
cut -c1-5 file # 取第 1-5 个字符
cut -f2- file # 取第 2 列及之后

sort

sort file                      # 排序
sort -n file # 数值排序
sort -r file # 逆序
sort -u file # 去重排序
sort -t: -k3 file # 按第 3 列排序
sort -k1,1 -k2,2n file # 多列排序

uniq

sort file | uniq               # 去重
sort file | uniq -c # 统计出现次数
sort file | uniq -d # 只显示重复行
sort file | uniq -u # 只显示不重复行

tr

tr 'a-z' 'A-Z' < file          # 小写转大写
tr -d '0-9' < file # 删除数字
tr -s ' ' < file # 压缩空格
tr -d -c 'a-zA-Z' < file # 只保留字母

wc

wc -l file                     # 统计行数
wc -w file # 统计单词数
wc -c file # 统计字节数
wc -m file # 统计字符数

信号处理

# trap 语法
trap 'commands' signals

# 常用示例
trap 'echo "Interrupted"; exit' INT
trap 'cleanup; exit' EXIT
trap '' INT # 忽略信号
trap - INT # 恢复默认行为

常见信号

信号编号含义触发方式
SIGHUP1挂起终端关闭
SIGINT2中断Ctrl+C
SIGQUIT3退出Ctrl+\
SIGKILL9强制终止kill -9
SIGTERM15终止kill
SIGUSR110用户定义kill -USR1
SIGUSR212用户定义kill -USR2

后台任务

cmd &               # 后台运行
nohup cmd & # 退出终端后继续运行
jobs # 查看后台任务
fg %1 # 调到前台
bg %1 # 放到后台
wait # 等待所有后台任务
wait $pid # 等待指定进程
wait -n # 等待任意一个完成
disown %1 # 从任务列表移除

进程管理

ps aux              # 查看进程
pstree # 查看进程树
pgrep name # 查找进程 PID
kill PID # 终止进程
kill -9 PID # 强制终止
killall name # 按名称终止
pkill pattern # 按模式终止
nice -n 10 cmd # 以较低优先级运行
renice -n 5 -p PID # 修改优先级

调试

bash -n script.sh   # 检查语法
bash -x script.sh # 打印执行的命令
bash -v script.sh # 打印读取的行

# 脚本内
set -x # 开启调试
set +x # 关闭调试
set -e # 遇错退出
set -u # 未定义变量报错

# 使用 trap 调试
trap 'echo "Line $LINENO: $BASH_COMMAND"' DEBUG

安全检查清单

变量处理

  • 所有变量都用双引号包围:"$var"
  • 使用 set -u 捕获未定义变量
  • 避免使用 eval
  • 使用 local 声明局部变量

输入验证

  • 验证用户输入(白名单优于黑名单)
  • 限制输入长度
  • 验证文件路径,防止路径遍历
  • 检查危险字符:; | & $ \ ( ) < >`

文件操作

  • 使用 mktemp 创建临时文件
  • 设置安全权限:chmod 600
  • 使用 trap 清理临时文件
  • 验证文件路径在允许范围内

敏感数据

  • 不硬编码密码
  • 使用环境变量或配置文件
  • 日志中过滤敏感信息
  • 使用后清理敏感变量

快捷键

快捷键功能
Tab自动补全
Ctrl+C终止命令
Ctrl+D退出 Shell
Ctrl+L清屏
Ctrl+A光标移到行首
Ctrl+E光标移到行尾
Ctrl+U删除光标前内容
Ctrl+K删除光标后内容
Ctrl+R搜索历史
Ctrl+Z暂停任务
Ctrl+W删除前一个单词

通配符

符号含义
*匹配任意字符
?匹配单个字符
[abc]匹配 a、b、c
[a-z]匹配范围
[!abc]不匹配
{a,b}匹配 a 或 b

花括号扩展

{a,b,c}             # a b c
{1..5} # 1 2 3 4 5
{a..e} # a b c d e
{1..10..2} # 1 3 5 7 9
file{,.bak} # file file.bak
dir_{a,b}/file # dir_a/file dir_b/file

常用命令

文件操作

ls -la              # 列出文件
cp source dest # 复制
mv source dest # 移动/重命名
rm file # 删除文件
rm -rf dir # 删除目录
mkdir -p dir # 创建目录
touch file # 创建空文件
ln -s target link # 创建符号链接
find . -name "*.txt" # 查找文件

文件查看

cat file            # 显示内容
less file # 分页查看
head -n 20 file # 前 20 行
tail -n 20 file # 后 20 行
tail -f file # 实时追踪
wc -l file # 统计行数

网络工具

ping host           # 测试连通
curl url # 请求 URL
wget url # 下载文件
ssh user@host # SSH 连接
scp file user@host:path # 复制文件

参考资料