Shell 基础复习笔记:执行方式 · 变量 · 运算符

复习原因:旧教程写法过时(sh / 反引号 / $[ ] / expr)+ 基础不熟
日期:2026-10-15 · 定位:所有脚本知识的"地基"


一、脚本执行方式(本质区别:子进程 vs 当前 shell)

方式 命令 特点 适用
① 显式解释 bash p1.sh 免执行权限;子进程,变量改动不保留 日常最保险
② 直接执行 ./p1.sh 需 chmod +x + 首行 #!/bin/bash;子进程 发布/安装脚本
③ 当前 shell source p1.sh(或 . p1.sh) 不建子进程,变量/函数改动保留 加载配置(.bashrc)

⚠️ 易错点:
- 绝对路径执行(/home/u/s.sh)= 方式②,是子进程,不是当前 shell!
- 老教程的 sh s.sh 在 Debian 是 dash(更严格),[[ ]] 等特性会报错 → 统一用 bash
- 记忆:"执行"= 子进程,"source"= 当前 shell


二、变量(最容易出错的模块)

1. 定义:等号两边不能有空格

name=value     # ✅
name = value   # ❌ 被解析成"执行命令 name,参数 = value"

2. 引用规则

echo $name        # 取变量值
echo ${name}      # 取变量值,花括号标边界 → 推荐
echo "$name"      # 双引号:展开,整体当一个词 → 生产必须加引号
echo '$name'      # 单引号:字面量,输出 $name
a=world
echo "$a"     # world
echo '$a'     # $a(不展开)

3. 命令替换

today=$(date +%Y%m%d)    # ✅ 现代
today=`date +%Y%m%d`     # ❌ 老式(嵌套难、转义地狱)

4. 位置参数与特殊变量

# bash t.sh apple banana
$0 → t.sh            $1 → apple      $2 → banana
$# → 2(个数)        $@ → 全部参数    $? → 上条命令退出码(0=成功)
$$ → 当前 PID

经典坑:$@ vs "$@"

# 传参 "hello world" 和 "bob"
for x in $@;  do echo "$x"; done   # 拆成 hello / world / bob
for x in "$@"; do echo "$x"; done  # hello world / bob ✅

三、运算符

1. 算术(只支持整数)

x=5; y=2
echo $((x + y))    # 7
echo $((x / y))    # 2 —— 整除向下取整,没有小数!
echo $((x % y))    # 1
((x++))            # 自增

老写法 $[ ] / expr 全部淘汰。

2. 比较三分类

# 数值:[ ] 和 [[ ]] 通用
[ $x -eq 5 ]    # -eq -ne -gt -ge -lt -le

# 字符串(= 是一个,不是 ==)
[ "$s" = "abc" ]     # 相等(引号必须,防空变量)
[ -z "$s" ]          # 为空
[ -n "$s" ]          # 非空
[[ "abc" =~ ^a ]]    # 正则(仅 [[ ]] 支持)

# 文件
[ -e 文件 ] 存在  [ -f ] 普通文件  [ -d ] 目录
[ -r ] [ -w ] [ -x ]  读/写/执行权限

3. [ ] vs [[ ]](老教程最大的坑)

[ ](test 命令) [[ ]](bash 关键字)
空变量 [ $s = a ] 报错 [[ $s == a ]] 安全
逻辑组合 -a / -o 直接 && / \|\|
正则 不支持 =~ 支持
比较符 = = 或 ==
[[ $a == x && $b == y ]]     # 现代标准
[ "$a" = x -a "$b" = y ]    # 老式,能跑但坑多

四、老教程 4 大过时写法速查

场景 老教程 ❌ 现代 ✅
命令替换 `cmd` $(cmd)
算术 $[x+1] / expr $((x+1))
测试 test / [ ] [[ ]]
逻辑组合 [ a -a b ] [[ a && b ]]

五、自测批改记录(2026-10-15)

Q1 执行方式:bash 免权限子进程 ✅ / ./ 需权限子进程 ✅ / source 当前 shell ✅
- ❌ 我答错点:绝对路径执行也是子进程(= 方式②),不是当前 shell

Q2 单双引号:'$a' → $a(字面),"$a" → world(展开)✅

Q3 位置参数:参数 "hello world" bob → $#=2、$1="hello world"、"$@" 保持两个独立参数、$@ 拆成 3 词 ✅

Q4 整除:$((7/2)) → 3(bash 算术只支持整数,除法向下取整)✅

Q5 老→新改写(我错的 3 处):

b=$((a + 1)      # ❌ 括号不配对 → $((a + 1)) 双括号成对
&& &b -lt 2030   # ❌ &b → $b(& 是逻辑与,不是变量引用)
2030]]           # ❌ [[ ]] 内每词必须空格 → -lt 2030 ]]

六、语法三查习惯(每次写完脚本必做)

① 数括号:$(( → 后面一定有两个 ))
② 数美元:每个变量前都有 $,且 $ 后一定是变量名
③ 查空格:[[ 内容 ]] 首尾都有空格;[ 内容 ] 同样

病根提醒:思想对 + 书写精度不够 = 语法错误。三查习惯能把错误消灭在运行前。

🔗 相关笔记