适用人群:已掌握三剑客基础用法,希望进阶生产环境实战的运维/开发工程师目标:从“能写脚本”到“能高效处理大规模日志、能优化性能、能解决复杂文本问题”
| grep | |||
| sed | |||
| awk |
生产环境选型铁律:grep 做“筛选”,sed 做“替换”,awk 做“分析”。三者常组合使用,形成“grep 过滤 → sed 清洗 → awk 统计”的流水线。
-E | egrep,支持 |、+、?、{n,m} | |
-P | \d、\w、s、lookahead | |
-o | ||
-c | ||
-A n / -B n / -C n | ||
-l / -L | ||
-r / -R | ||
--exclude--include | .log,跳过 .gz |
字符类简写:
bash
\d # 数字 → [0-9]\w # 单词 → [A-Za-z0-9_]\s # 空白 → [ \t\n\r\f\v]\D \W \S # 对应反义
量词与分组:
bash
{n,m}# 出现 n 到 m 次+ # 1 次或多次(等于 {1,})? # 0 次或 1 次(等于 {0,1})(...)# 捕获分组,后面可用 \1 引用
零宽断言(Perl 正则):
bash
(?=pattern)# 正向先行断言:后面跟着 pattern(?!pattern)# 负向先行断言:后面不跟着 pattern(?<=pattern)# 正向后行断言:前面是 pattern(?<!pattern)# 负向后行断言:前面不是 pattern
提取 Nginx 日志中的真实客户端 IP(含代理链):
bash
grep-oP'(?<![0-9.])[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(?![0-9.])' access.log |head-5
快速统计日志中某个错误码在每小时的分布(正则截取日期+提取数据):
bash
grep-E'ERROR|FATAL' app.log |grep-o'2026-08-12 [0-9]{2}:00'|sort|uniq-c
在 /var/log 下递归查找所有包含 Out of memory 的 *.log 文件:
bash
grep-rl--include="*.log""Out of memory" /var/log/
从混合日志中同时提取多个模式的上下文(且忽略大小写):
bash
grep-E-i'panic|fatal|segfault'-C5 app.log
基本语法:sed [options] 'command' file
s/old/new/ | |
s/old/new/g | |
s/old/new/2 | |
s/old/new/p | -n 搭配) |
d | |
p | -n) |
ai | |
c | |
n | |
N | |
y/source/dest/ | |
rw | |
q | |
= |
寻址方式:
bash
sed-n'5p'file# 打印第 5 行sed-n'5,10p'file# 打印 5-10 行sed'5,10d'file# 删除 5-10 行sed'/error/d'file# 删除包含 error 的行sed'/start/,/end/p'# 从匹配 start 的行到匹配 end 的行
bash
# 将 2026-08-12 改为 08/12/2026sed-E's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\2\/\3\/\1/g'file
在 sed 中,用 \( \) 捕获(基础正则)或 ( )(扩展正则 -E),用 \1、\2 引用。
匹配难度较大的 & 引用(取整行匹配):
bash
echo"hello world"|sed-E's/[a-z]+/[\&]/g'# 输出:[hello] [world]
模式空间(Pattern Space):sed 默认的处理缓冲区,逐行读入并执行命令
保持空间(Hold Space):辅助缓冲区,用于跨行数据的暂存
交换保持空间与模式空间(x)、追加保持空间到模式空间(G):
bash
# 反转文件行序(tac 的 sed 实现)sed'1!G;h;$!d'file
多行替换(处理跨行):
bash
# 将跨行的 <tag>...</tag> 合并为一行sed-n'/<tag>/{:a;N;/<\/tag>/!ba;s/\n/ /g;p}'file
批量替换配置文件中所有 localhost 为 127.0.0.1,仅替换前 5 个匹配项:
bash
sed-i's/localhost/127.0.0.1/5' config.ini
从 /etc/passwd 中提取用户名和家目录(打印第 1 和第 6 字段),并删除以 # 开头的注释行与空白行:
bash
sed-E-e'/^#/d'-e'/^$/d'-e's/^([^:]+):.*:([^:]+)$/\1 \2/' /etc/passwd
将 JSON 日志中的 ISO 8601 时间戳 2026-08-12T14:30:00Z 替换为 Unix 时间戳:
bash
# 使用 date 命令配合 sed 的 e 修饰符(GNU sed)sed-E's/([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)/'"$(date-d'\1' +%s)"'/g' file
text
BEGIN{...} → 逐行处理 → END{...}每行处理:自动按 FS(字段分隔符)分割成 $1...$NF,$0 为整行,NR 为行号,NF 为字段数。
-F | -F,、-F'[ :]+' |
FS | |
OFS | |
RS | |
ORS | |
NR | |
NF | |
$0 | |
$n |
字符串函数:
bash
length($0)# 字符串长度substr($1, 2, 3)# 子串(从第2位开始取3位)split($0, arr, ",")# 分割成数组 arrindex($1, "abc")# 返回子串位置toupper($1) / tolower($1)
数学函数:
bash
sqrt($1)# 平方根int($1)# 取整rand()# 随机数(需先 srand())
时间函数:
bash
systime()# 当前 Unix 时间戳strftime("%Y-%m-%d", systime())
bash
# 关联数组(统计 IP 访问量)awk'{count[$1]++} END {for(ip in count) print ip, count[ip]}' access.log# 遍历数组的两种方式for(key in array){... }# 无序for(i=1; i<=length(array); i++){}# 有序(需额外处理)# 删除数组元素delete array[key]
分析 Nginx 访问日志,统计每个状态码的数量、最大响应时间、平均响应时间:
bash
awk'{code=$9; time=$10; total[code]++; sum[code]+=time; if(time>max[code]) max[code]=time} END {for(c in total) printf "%s: count=%d avg=%.2f max=%.2f\n", c, total[c], sum[c]/total[c], max[c]}' access.log
处理多行日志(如 Java 堆栈,RS 设为空行):
bash
awk'BEGIN{RS=""; FS="\n"} /OutOfMemoryError/{print "==== Stack Trace ====\n" $0}' app.log
合并两个文件(类似 JOIN):
bash
# user.csv: id,name# order.csv: user_id,order_id,amountawk -F, 'NR==FNR{a[$1]=$2; next} {print $0, a[$1]}' user.csv order.csv
从大量 JSON 格式的日志中提取 latency 字段并输出到 CSV:
bash
grep'"level":"ERROR"' app.log |awk -F'"''{for(i=1;i<=NF;i++) if($i=="latency") print $(i+2)}'|sort-n|head-10
bash
# 1. 用 grep 快速过滤出 ERROR 级别日志# 2. 用 sed 清洗不需要的字段、去掉时间戳# 3. 用 awk 按接口聚合统计grep'ERROR' app.log \|sed-E's/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} //'\|awk -F'|''{count[$2]++; sum[$2]+=$4} END{for(i in count) print i, count[i], sum[i]/count[i]}'
黄金公式:grep 处理“有无”问题,sed 处理“要不要”问题,awk 处理“有多少”问题。
bash
# 使用 LC_ALL=C 禁用字符集处理,加速 grepLC_ALL=C grep'pattern' bigfile# 优先过滤再处理(减少 awk 处理的行数)awk'/ERROR/{...}' bigfile.log # 等价但不如 grep 快grep'ERROR' bigfile.log |awk'{...}'# 更快# 使用 mmap 读取(部分 awk 版本支持)awk-V|grep-i'gawk'# GNU awk 支持大文件更友好
grep -v | grep -v '^$' 或 awk 'NF' |
/ 未转义 | sed 's#a/b#c/d#g' |
$NF 当作变量 vs 字符串 | $NF"$NF" 是字符串 |
asorti() 或管道传递给 sort | |
file 或 iconv 转换编码 | |
sed -i | sed -i ''(BSD sed) |
| 初级 | grep -E 'pattern' | s/old/new/g | $1、$NF |
| 中级(本指南目标) | -P、-o、上下文、递归 | ||
| 高级 |
掌握三剑客的核心在于把复杂的文本问题拆解成“筛选 → 清洗 → 统计”三个步骤,然后选用合适的工具完成。持续练习日志分析、配置管理、监控脚本这三个典型场景,技能会快速提升。