Shell 脚本与三剑客实战(写脚本 + grep/sed/awk 处理文本)
分类:Shell脚本与三剑客
标签: Shell、脚本、grep、sed、awk、正则、管道
摘要: 日常运维很多重复操作,写个脚本一次跑完。本文从”脚本怎么搭骨架”讲到”怎么批量处理文本”,把 shell 语法和三剑客 grep / sed / awk 一起讲透,含正则地基地和一条流水线的实战。
一、脚本的骨架(三步固定)
#!/bin/bash # 第1行,声明用 bash 解释
chmod +x 脚本.sh # 第2步,加执行权限
./脚本.sh # 第3步,运行(或用 bash 脚本.sh)
变量 / 输入:
name="zhu" # 定义变量(= 两边不能有空格!)
echo $name # 用变量
read var # 让用户输入
位置参数(传参):
./a.sh hello world
# $0=脚本名 $1=hello $2=world $#=参数个数 $@=所有参数
引号区别(常考):
'单引号' # 是啥就是啥,不解析变量
"双引号" # 会解析里面的 $变量
`反引号` # 执行命令取结果(等价 $( ))
二、逻辑三件套:if / for / case
if [ $a -eq $b ]; then
echo "相等"
else
echo "不等"
fi
# 数字比较:-eq等 -ne不等 -gt大于 -lt小于 -ge≥ -le≤
# 文件判断:-e存在 -f是文件 -d是目录
# 逻辑组合:&&和 ||或 !非
for i in 1 2 3; do echo $i; done # 固定次数循环
while [ 条件 ]; do ...; done # 条件循环
case $1 in # 多分支(类似 switch)
start) echo "启动";;
stop) echo "停止";;
*) echo "未知";;
esac
函数 & 必背技巧:
myfunc() { echo "这是函数"; }
myfunc # 调用
$? # 上一条命令成功否(0=成功)★排障常看
$(命令) # 命令结果当值用:echo "今天 $(date)"
> 覆盖写 >> 追加写 2> 错误输出 | 管道
exit 0 # 脚本退出码
三、正则基础(三剑客的地基,先看这个)
^ 行开头 ^a 以a开头
$ 行结尾 b$ 以b结尾
. 任意一个字符
[] 集合 [abc]=a或b或c;[0-9]=数字;[a-z]=小写字母
[^] 排除 [^0-9]=非数字
* 前一个出现0次或多 ab* → a,ab,abb
+ 前一个出现1次或多(需-E)ab+ → ab,abb
? 前一个0次或1次(需-E)ab? → a,ab
| 或(需-E) a|b → a 或 b
{n} 出现n次 a{2} → aa
四、三剑客分工(一句话记牢)
grep 负责”找行”,sed 负责”改行”,awk 负责”取列/统计”。
grep —— 找内容 / 过滤
grep 关键词 文件 # 基本搜索
grep -i 关键词 文件 # 忽略大小写
grep -n 关键词 文件 # 带行号
grep -c 关键词 文件 # 只返回命中行数
grep -v 关键词 文件 # 取反:不含关键词的行
grep -r 关键词 目录/ # 递归搜整个目录
grep -E "a|b" 文件 # 扩展正则(用 | + 等)
grep -A2 "关键词" 文件 # 匹配行 + 后面2行(看上下文)
# 实战:看 nginx 报错
grep -i error /var/log/nginx/error.log | tail
sed —— 替换 / 删行
sed 's/旧/新/' 文件 # 每行替换第一个匹配
sed 's/旧/新/g' 文件 # 全局替换(g=global)
sed -i 's/旧/新/g' 文件 # -i 就地直接改文件 ★改前先预览
sed -n '3,5p' 文件 # 只打印第3~5行
sed '1,5d' 文件 # 删第1~5行
# 稳妥三步:先看效果 → 再 -i 落盘
sed 's/8080/8081/g' nginx.conf # 预览
sed -i 's/8080/8081/g' nginx.conf # 确认后才改
awk —— 按列处理 / 统计
awk '{print $1}' 文件 # 取第1列(默认按空白分列)
awk -F: '{print $1}' /etc/passwd # -F 指定分隔符(按 : 分)
awk '{print NR, $0}' 文件 # NR=行号,$0=整行
awk '$3 > 50 {print}' 文件 # 条件:第3列>50才打印
awk '{s+=$1} END{print s}' 文件 # 第1列求和
awk 'END{print NR}' 文件 # 统计总行数
# ★明星案例:统计访问日志 IP 次数并降序
awk '{print $1}' access.log | sort | uniq -c | sort -rn
# 取IP列 → 排序 → 去重计数 → 按次数降序
五、三剑客配合管道(最常用的一条流水线)
# 读日志→过滤含blog→取IP列→计数→降序→看前10
cat access.log | grep blog | awk '{print $1}' | sort | uniq -c | sort -rn | head
六、踩坑速记
| 坑 | 现象 | 解决 |
|---|---|---|
| 变量赋值报错 | command not found | = 两边不能有空格 |
| 中文乱码/引号 | 结果不对 | 用英文半角引号 ' " |
| sed 改完发现错了 | 文件被改坏 | 先预览,重要文件 cp 备份 |
| 正则不生效 | + ? | 没效果 | 加 -E 用扩展正则 |
| 脚本不执行 | Permission denied | chmod +x 脚本 |