📖 知识点简介
日志分析、配置修改、数据提取是运维的日常三件套。grep、sed、awk 被誉为 Linux 文本处理"三剑客",是运维工程师必须掌握的利器:
- grep --- 文本搜索过滤,快如闪电
- sed --- 流式编辑替换,批量改配置利器
- awk --- 结构化数据提取,列操作王者
三者配合使用,能解决 90% 的日常文本处理需求。今天用实战场景逐个击破。
🛠 核心命令整理
1️⃣ grep --- 文本搜索过滤器
bash
# 基础搜索
grep "error" app.log # 搜索含 error 的行
grep -i "error" app.log # 忽略大小写
grep -v "debug" app.log # 排除含 debug 的行
grep -n "error" app.log # 显示行号
# 进阶用法
grep -c "error" app.log # 统计匹配行数
grep -r "timeout" /var/log/ # 递归搜索目录
grep -l "500" /var/log/nginx/*.log # 只显示文件名
grep -A 3 -B 2 "OOM" syslog # 显示匹配行前后文(A后B前)
grep -E "error|fatal|critical" app.log # 扩展正则,多关键字匹配
grep -P "\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}" access.log # Perl正则匹配IP
2️⃣ sed --- 流式编辑器
bash
# 替换操作(核心场景)
sed 's/old/new/' file # 每行第一个 old 替换为 new
sed 's/old/new/g' file # 全局替换(g 标记)
sed 's/old/new/gi' file # 全局替换 + 忽略大小写
sed -i 's/old/new/g' file # -i 直接修改文件(慎用!)
sed -i.bak 's/old/new/g' file # 备份原文件后替换
# 行操作
sed -n '10,20p' file # 打印 10-20 行
sed '5d' file # 删除第 5 行
sed '/^#/d' config.conf # 删除注释行
sed '/^$/d' file # 删除空行
sed '3a\newline' file # 在第 3 行后追加
# 实战场景
sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf # 改端口
sed -i '/^MaxClients/c\MaxClients 500' /etc/httpd/conf/httpd.conf # 修改配置行
3️⃣ awk --- 列处理与报表生成
bash
# 基础字段提取
awk '{print $1}' file # 打印第一列
awk '{print $1, $NF}' file # 第一列和最后一列
awk -F: '{print $1, $3}' /etc/passwd # 指定分隔符(:)
# 条件过滤
awk '$3 > 100 {print $1, $3}' stats.txt # 第三列大于 100
awk '/error/ {print $0}' app.log # 匹配 error 的行整行输出
awk 'NR==5' file # 打印第 5 行
awk 'NR>=10 && NR<=20' file # 打印 10-20 行
# 内置变量与格式化
awk '{sum+=$1} END {print "总和:", sum}' data.txt # 求和
awk '{sum+=$1; count++} END {print "平均:", sum/count}' # 求平均
awk '{printf "%-20s %8d\n", $1, $2}' file # 格式化输出
# 数组与去重
awk '!seen[$0]++' file # 去除重复行
awk '{count[$1]++} END {for(ip in count) print ip, count[ip]}' access.log # IP 计数
🔧 实操示例:Nginx 日志分析实战
假设有一份 Nginx 访问日志 access.log,格式如下:
arduino
192.168.1.1 - - [25/Jun/2026:10:15:30 +0800] "GET /api/users HTTP/1.1" 200 1234
10.0.0.5 - - [25/Jun/2026:10:15:31 +0800] "POST /api/login HTTP/1.1" 401 56
192.168.1.1 - - [25/Jun/2026:10:16:00 +0800] "GET /api/orders HTTP/1.1" 500 89
场景 1:统计各 IP 的访问次数
bash
awk '{print $1}' access.log | sort | uniq -c | sort -rn
场景 2:找出所有 5xx 错误
bash
awk '$9 ~ /^5[0-9]{2}/ {print $1, $7, $9}' access.log
场景 3:统计每个 API 的请求次数(去 URL 参数)
bash
awk '{split($7, a, "?"); print a[1]}' access.log | sort | uniq -c | sort -rn
场景 4:提取特定时间范围的日志
bash
sed -n '/25/Jun/2026:10:15/,/25/Jun/2026:10:30/p' access.log
场景 5:三剑客组合拳 --- 找最活跃的 IP 并提取其请求
bash
# 找出请求最多的 IP
top_ip=$(awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -1 | awk '{print $2}')
echo "最活跃 IP: $top_ip"
# 提取该 IP 的所有 5xx 错误
grep "$top_ip" access.log | awk '$9 ~ /^5[0-9]{2}/'
⚠️ 常见坑点与注意事项
grep 篇
- 正则差异 :
grep默认是基础正则(BRE),|+?等需要用-E启用扩展正则,或加反斜杠转义 - 二进制文件 :
grep遇到二进制文件会输出Binary file matches,加-a强制文本模式 - 大文件搜索 :用
-m N限制匹配行数,避免刷屏,如grep -m 10 "error" huge.log
sed 篇
-i一定要备份 :生产环境养成习惯sed -i.bak 's///g' file,配置改错只需mv file.bak file- 定界符选择 :如果路径含
/,换用|或#做定界符:sed 's|/var/www|/srv/www|g' file - 多行模式 :sed 默认逐行处理,跨行匹配需要用
N(多行模式),复杂场景建议换 awk
awk 篇
- 变量作用域 :
awk中$1、$2是字段变量,NR、NF是内置变量,自定义变量不需加$ - 分隔符踩坑 :默认分隔符是空白(空格/Tab),如果字段内有空格要用
-F指定,如-F '","'处理 CSV - 浮点数比较 :awk 的数值比较用
><==,但字符串比较用~(匹配)或==(精确) - 性能注意 :awk 逐行处理大文件性能很好,但频繁用
system()调用外部命令会急剧变慢
💡 一句话口诀
grep 搜索行,sed 改内容,awk 切字段 grep 快且准,sed 批量改,awk 算统计 三剑客配管道,运维效率翻一番 🚀