考前 10 分钟看这一页。全部是「反直觉」和「高频踩坑」。
🚨 空格类(最常见)
| ❌ 错误 |
✅ 正确 |
说明 |
a = 1 |
a=1 |
赋值等号两侧不能有空格 |
[$a==$b] |
[ $a == $b ] |
方括号内侧必须有空格 |
expr 2+2 |
expr 2 + 2 |
运算符两侧要有空格 |
expr 2 * 3 |
expr 2 \* 3 |
乘号要转义 |
🚨 符号类
| ❌ 错误 |
✅ 正确 |
说明 |
echo 'Hello $name' |
echo "Hello $name" |
单引号不解析变量 |
`expr 2 + 2` → 写成 'expr 2 + 2' |
用反引号 |
命令替换用 ` 不是 ' |
$10 取第 10 个参数 |
${10} |
n≥10 必须加花括号 |
. 和文件名连写 |
. ./lib.sh |
source 的 . 后要留空格 |
2 >file |
2>file |
2 和 > 必须连着写 |
🚨 逻辑类
| 坑 |
真相 |
$? 是 0 → 认为是假 |
0 代表真/成功,非 0 才是失败 |
$? 随便什么时候读都行 |
$? 只对紧邻的上一条命令负责 |
return "字符串" |
return 只能返回 0~255 整数 |
[ "$a" = "$b" ] 和 [ "$a" -eq "$b" ] 混用 |
字符串用 =,数值用 -eq |
[ -f $file ] 不加引号 |
变量必须加双引号,防空值报错 |
🚨 语法结构类
| 结构 |
结尾 |
记忆 |
if |
fi |
if 倒写 |
case |
esac |
case 倒写 |
for/while/until |
done |
— |
| 每个 case 分支 |
;; |
相当于 break |
- sh 流程控制不可为空:else 分支没内容就别写
- 函数必须先定义后使用
- 结尾的 Here Document delimiter 必须顶格写
- 数组元素用空格分隔,不是逗号
🚨 引号总结
| 引号 |
变量 |
转义 |
单引号能否出现 |
' ' |
不解析 |
不解析 |
不能(成对可拼接) |
" " |
解析 |
解析 |
可以 |
🚨 比较运算符对照
| 用途 |
单括号 [ ] |
双括号 <span class="deadlink"></span> / (( )) |
| 数值比较 |
-eq -ne -gt -lt -ge -le |
== != > < >= <= |
| 字符串比较 |
= != |
== != |
| 正则匹配 |
不支持 |
[[ $v =~ ^[0-9]+$ ]] |
| 模式匹配 |
不支持 |
<span class="deadlink">$v == *.log</span> |
🚨 重定向速记
| 写法 |
含义 |
> file |
覆盖输出 |
>> file |
追加重定向 |
2> file |
错误输出到文件 |
> file 2>&1 |
正常+错误都进文件 |
> /dev/null 2>&1 |
全部丢弃(静默) |
<< EOF |
Here Document |
🚨 特殊变量速查
$0 脚本名 | $1..$9 参数 | ${10} 第10个参数 | $# 参数个数 | $* 全部参数(单串) | $@ 全部参数(独立) | $$ 进程ID | $! 后台进程ID | $? 上条命令退出状态
🔗 关联
Shell-学习总览|上一课 → 12-实战脚本合集|深度学习-七天冲刺计划