为什么叫"三剑客"
grep、sed、awk被称为Linux文本处理三剑客,因为它们各有所长:
| 工具 | 擅长领域 | 一句话总结 |
|---|
grep | 搜索/过滤 | 找出包含关键词的行 |
sed | 替换/编辑 | 对文本做查找替换 |
awk | 分析/统计 | 按列处理和统计数据 |
服务器运维中,日志分析、配置修改、数据提取都离不开这三个工具。我几乎每天都在用。
grep:文本搜索
基本用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 在文件中搜索关键词
$ grep "error" /var/log/syslog
Jan 17 10:01:23 server kernel: [error] something went wrong
Jan 17 10:05:45 server nginx: 2026/01/17 10:05:45 [error] 1234#0
# 忽略大小写
$ grep -i "error" /var/log/syslog
# 显示行号
$ grep -n "error" /var/log/syslog
142:Jan 17 10:01:23 server kernel: [error] something went wrong
256:Jan 17 10:05:45 server nginx: 2026/01/17 10:05:45 [error] 1234#0
# 显示匹配行的前后几行
$ grep -C 3 "error" /var/log/syslog # 前后各3行
$ grep -B 2 "error" /var/log/syslog # 前2行
$ grep -A 2 "error" /var/log/syslog # 后2行
|
常用参数
| 参数 | 功能 | 示例 |
|---|
-i | 忽略大小写 | grep -i "error" log |
-n | 显示行号 | grep -n "error" log |
-r | 递归搜索 | grep -r "TODO" /src/ |
-v | 反向匹配 | grep -v "debug" log |
-c | 统计匹配行数 | grep -c "error" log |
-l | 只显示文件名 | grep -rl "error" /var/log/ |
-E | 使用正则 | `grep -E “error |
实战示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 查找Nginx的404错误
$ grep "\" 404" /var/log/nginx/access.log
203.0.113.5 - - [17/Jan/2026:10:00:00 +0000] "GET /notfound HTTP/1.1" 404 162
# 统计每种HTTP状态码的数量
$ grep -oP '\" \K\d{3}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
1523 200
234 301
89 404
12 500
# 递归搜索代码中的TODO
$ grep -rn "TODO" /var/www/myproject/ --include="*.py"
/var/www/myproject/app.py:45: # TODO: 添加错误处理
/var/www/myproject/utils.py:12: # TODO: 优化性能
|
sed:流编辑器
基本替换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 替换第一个匹配项
$ echo "hello world" | sed 's/hello/hi/'
hi world
# 替换所有匹配项(加g标志)
$ echo "aaa bbb aaa" | sed 's/aaa/ccc/g'
ccc bbb ccc
# 直接修改文件(-i参数)
$ sed -i 's/old_text/new_text/g' config.txt
# 安全的做法:先备份再修改
$ sed -i.bak 's/old_text/new_text/g' config.txt
# 会自动创建config.txt.bak备份
|
常用操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 删除包含关键词的行
$ sed -i '/pattern/d' file.txt
# 删除空行
$ sed -i '/^$/d' file.txt
# 在第3行后插入内容
$ sed -i '3a\新的一行内容' file.txt
# 在第3行前插入内容
$ sed -i '3i\新的一行内容' file.txt
# 只处理第5到10行
$ sed -n '5,10p' file.txt
# 替换某一行的内容
$ sed -i '5s/.*/新的第5行内容/' file.txt
|
实战示例
1
2
3
4
5
6
7
8
9
10
11
12
| # 修改Nginx配置中的端口
$ sed -i 's/listen 80;/listen 8080;/g' /etc/nginx/sites-available/default
# 批量修改配置文件中的IP
$ sed -i 's/192.168.1.100/10.0.0.50/g' /etc/nginx/conf.d/*.conf
# 去掉配置文件中的注释行
$ sed '/^#/d; /^$/d' /etc/nginx/nginx.conf
# 只显示有效配置,不修改文件(没有-i)
# 在配置文件特定位置插入内容
$ sed -i '/server_name/a\ proxy_set_header Host $host;' /etc/nginx/conf.d/mysite.conf
|
awk:数据分析
基本用法
awk按列处理数据,默认以空格/Tab分隔。
1
2
3
4
5
6
7
8
| # 打印第1列和第3列
$ echo "John 25 Engineer" | awk '{print $1, $3}'
John Engineer
# 处理文件
$ awk '{print $1, $4}' /var/log/nginx/access.log
203.0.113.5 [17/Jan/2026:10:00:00
198.51.100.3 [17/Jan/2026:10:01:23
|
指定分隔符
1
2
3
4
5
6
7
8
9
10
11
| # 处理/etc/passwd(冒号分隔)
$ awk -F: '{print $1, $3, $7}' /etc/passwd
root 0 /bin/bash
daemon 1 /usr/sbin/nologin
www-data 33 /usr/sbin/nologin
deploy 1000 /bin/bash
# 用Tab作为输出分隔符
$ awk -F: 'BEGIN{OFS="\t"} {print $1, $3}' /etc/passwd
root 0
daemon 1
|
内置变量
| 变量 | 含义 |
|---|
$0 | 整行 |
$1-$N | 第N列 |
NR | 行号 |
NF | 当前行的列数 |
FS | 输入分隔符 |
OFS | 输出分隔符 |
条件过滤
1
2
3
4
5
6
7
8
| # 打印第3列大于1000的行(找普通用户)
$ awk -F: '$3 >= 1000 {print $1, $3}' /etc/passwd
deploy 1000
testuser 1001
# 打印包含error的行
$ awk '/error/ {print NR, $0}' /var/log/syslog
142 Jan 17 10:01:23 server kernel: [error] something went wrong
|
实战示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # 统计Nginx日志中每个IP的访问次数(Top 10)
$ awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
1523 203.0.113.5
892 198.51.100.3
456 192.0.2.100
# 统计每小时的请求量
$ awk '{print $4}' /var/log/nginx/access.log | cut -d: -f2 | sort | uniq -c
120 08
350 09
890 10
756 11
445 12
# 计算日志文件中响应时间的平均值
$ awk '{sum+=$NF; count++} END{print "平均响应时间:", sum/count, "ms"}' response_times.log
平均响应时间: 125.6 ms
# 统计磁盘使用超过80%的分区
$ df -h | awk 'NR>1 {gsub(/%/,"",$5); if($5>80) print $6, $5"%"}'
/data 85%
|
组合使用
三剑客经常组合使用,威力更大:
1
2
3
4
5
6
7
8
9
10
11
12
| # 找出访问量最大的IP,并查看它请求了哪些URL
$ TOP_IP=$(awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -1 | awk '{print $2}')
$ grep "$TOP_IP" /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -10
# 批量替换多个配置文件中的域名
$ grep -rl "old-domain.com" /etc/nginx/ | xargs sed -i 's/old-domain.com/new-domain.com/g'
# 分析SSH暴力破解(失败登录Top 10 IP)
$ grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
523 203.0.113.50
234 198.51.100.99
89 192.0.2.200
|
总结
| 场景 | 用什么 |
|---|
| 搜索特定内容 | grep |
| 替换文本内容 | sed |
| 按列统计分析 | awk |
| 复杂日志分析 | 三者组合 |
学会这三个工具,日志分析和文本处理基本就不在话下了。
更多Linux基础命令可以参考Linux最常用的50个命令速查表。日志分析的更多技巧,推荐阅读Linux日志管理与分析。