一、Shell 基础概念
1. 什么是 Shell
Shell 是命令行解释器,负责翻译用户命令 → 内核执行 → 返回结果。
Shell 脚本:批量编写多条命令,实现自动化运维。
常见解释器:bash(Linux 默认)、zsh(Mac 默认)、sh
脚本后缀 .sh 仅为标识,不决定能否执行。
2. 查看当前 Shell(Mac 必看)
bash
# 查看默认登录 Shell
echo $SHELL
# 查看当前真实运行 Shell
ps -p $$
⚠️ $SHELL 是用户默认 Shell,不会随脚本执行器改变!
3. 第一个脚本 HelloWorld
脚本规范首行(幻数)
bash
#!/bin/bash
echo "Hello World"
含义:指定用 bash 解释器执行脚本,必须在第一行。
三种执行方式
bash hello.sh/zsh hello.sh:无需执行权限,强制指定解释器(会忽略脚本第一行幻数)sh hello.sh:使用系统默认 sh 执行chmod +x hello.sh加权限后./hello.sh:读取脚本第一行幻数执行
⚠️ ./ 不能省略,代表当前目录。
二、Shell 注释语法
1. 单行注释
bash
# 单行注释
echo "test" # 行尾注释
2. 多行注释
bash
:<<EOF
这里是多行注释
可以写任意内容
EOF
EOF 为自定义标记,首尾必须一致。
三、Shell 变量(高频易错)
1. 变量定义规范
✅ 正确:name="zhangsan"
❌ 错误:name = "zhangsan"(等号绝对不能有空格)
2. 变量调用
bash
echo $name
echo ${name} # 推荐,边界更清晰
3. 变量分类
- 自定义变量:仅当前 Shell 进程有效
- 环境变量 :全局所有进程有效,
env查看
4. 只读变量
ini
readonly age=20
age=30 # 报错,不可修改
5. 删除变量
bash
unset name
⚠️ readonly 只读变量无法 unset 删除
6. 变量类型特性
Shell 是弱类型语言:所有变量默认都是字符串。
整数运算必须用:$(( ))
ini
a=10
b=20
c=$((a+b))
echo $c
四、字符串操作(必考)
1. 三种定义方式
ini
str1=hello
str2="hello world"
str3='hello shell'
2. 单引号 / 双引号区别
- 单引号 '' :原样输出,不解析变量
- 双引号 "" :解析
$变量,支持转义
ini
name=jack
str1='hi $name' # 输出 hi $name
str2="hi $name" # 输出 hi jack
3. 字符串长度
bash
str="abcd"
echo ${#str} # 4
4. 字符串截取
语法:${str:起始下标:截取长度}(下标从 0 开始)
bash
str="abcdefg"
echo ${str:0:3} # abc
echo ${str:2} # cdefg
5. 字符串拼接
直接拼接,无需加号
ini
a="hello"
b="world"
c="${a}${b}"
6. 字符串替换
bash
str="aaabbbccc"
echo ${str/aaa/xxx} # 替换第一个
echo ${str//b/BB} # 全部替换
五、echo 输出
bash
echo "hello" # 自动换行
echo `date` # 输出系统时间
六、数组
正确定义(❌ 不能用逗号)
bash
# 正确:空格分隔
arr=("张三" "李四" "坦克")
echo ${arr[0]} # 取单个
echo ${arr[@]} # 取所有
echo ${#arr[@]} # 数组长度
echo ${#arr[2]} # 单个元素长度
七、脚本参数
bash
echo $0 # 脚本名
echo $# # 参数个数
echo $* # 所有参数
八、运算符大全
1. 算术运算两种方式
方式1:$(( ))(推荐)
css
a=100
b=200
echo $((a+b))
echo $((a-b))
echo $((a*b))
echo $((a%b))
方式2:expr(必须空格、*需转义)
bash
expr $a + $b
expr $a * $b
2. 比较、逻辑运算
bash
echo $((a < b))
echo $((a > b))
echo $((a == b))
echo $((a != b))
echo $((a && b))
echo $((a || b))
九、文件测试运算符(A-Z 完整版 + 纠错)
⚠️ -n -z只判断字符串,不能判断文件!
⚠️ -h -L 都是软链接,没有判断硬链接的参数!
| 运算符 | 含义 |
|---|---|
| -a/-e | 文件/目录是否存在 |
| -d | 是否为目录 |
| -f | 是否为普通文件 |
| -r | 文件可读 |
| -w | 文件可写 |
| -x | 文件可执行 |
| -s | 文件存在且非空 |
| -h/-L | 软链接文件 |
| -b | 块设备 |
| -c | 字符设备 |
| -n | 字符串非空 |
| -z | 字符串为空 |
十、流程控制(全部修正错误写法)
1. if 判断
ini
if [ 条件 ]; then
逻辑
elif [ 条件 ]; then
逻辑
else
逻辑
fi
2. for 循环(三种正确写法)
写法1:区间遍历
bash
for i in {1..10}
do
echo $i
done
写法2:数组遍历
bash
arr=(1 2 3 4 5)
for i in ${arr[@]}
do
echo $i
done
写法3:C 语言风格(必须双层括号)
bash
sum=0
for ((i=1;i<=10;i++))
do
sum=$((sum+i))
done
echo $sum
重点纠错
❌ 错误:for(i=1;i<=10;i++)
✅ 正确:for ((i=1;i<=10;i++))
❌ 错误:for i in ("a","b")(Shell 不用逗号)
✅ 正确:for i in "a" "b"
3. while 循环
bash
sum=0
i=1
while [ $i -le 10 ]
do
sum=$((sum+i))
i=$((i+1))
done
echo $sum
4. case 分支
bash
i=1
case $i in
1) echo "是1";;
2) echo "是2";;
*) echo "其他";;
esac
十一、文件导入与 bc 计算器
1. 导入其他脚本
bash
source ./hello.sh
# 或
. ./hello.sh
2. bc 浮点运算
bash
res=$(echo "1.2+2.3" | bc)
echo $res
十二、重定向 & 文件描述符(核心重难点)
1. 三大默认文件描述符
0标准输入 stdin(键盘)1标准输出 stdout(屏幕)2标准错误 stderr(屏幕)
2. 四大重定向符号
>输出覆盖(清空文件写入)>>输出追加(末尾新增)<输入重定向(文件代替键盘输入)<<HereDoc 多行输入
3. 输入重定向 <
bash
wc -l < /etc/passwd
# 逐行读取文件
while read line
do
echo $line
done < test.txt
4. 多行重定向 <<EOF
bash
cat <<EOF
第一行内容
第二行内容
EOF
# 直接写入文件
cat > out.txt <<EOF
内容
EOF
⚠️ 结束标记必须顶格无空格
5. 标准输出、错误输出分离/合并
bash
# 分开保存
ls /etc /no 1>ok.log 2>err.log
# 合并保存(顺序不能反)
ls /etc /no > all.log 2>&1
ls /etc /no &> all.log
6. 临时重定向 VS 永久重定向 exec
- 命令 > file:仅当前命令生效
- exec 1>file:后续所有命令永久重定向
7. 自定义文件描述符(10 以上)
bash
# 只读打开
exec 11< test.txt
read -u 11 str
exec 11<&-
# 读写打开
exec 12<> test.txt
read -u 12 a
echo "hi" >&12
exec 12<&-
8. 重定向备份与恢复
bash
exec 13<&1 # 备份屏幕输出
exec 1> log.txt
echo "写入日志"
exec 1<&13 # 恢复屏幕
exec 13<&- # 关闭fd
9. 屏蔽输出 /dev/null
javascript
命令 > /dev/null 2>&1
十三、临时文件 & 日志实战
1. mktemp 安全临时文件
bash
tmp=$(mktemp /tmp/xxx.XXXXXX)
trap 'rm -f $tmp' EXIT # 退出自动删除
2. 日志函数(工程常用)
perl
log(){
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a run.log
}
十四、全书高频踩坑汇总(必背)
- 变量赋值
a=1等号不能有空格 - for C 循环必须
(( ))双层括号 - 数组、for-in 遍历只用空格分隔,不用逗号
$SHELL不代表当前脚本解释器- 重定向合并
>file 2>&1顺序不能反 - 自定义 fd 必须 10 以上,用完必须关闭
-n -z只判断字符串,不判断文件- HereDoc 结束标记必须顶格