Linux 文本处理三剑客:grep、sed、awk 从入门到精通案例详解
作者:渣渣盟

📖 前言
在 Linux 的世界里,每天打交道最多的就是文本——日志文件、配置文件、脚本代码……几乎所有的系统信息都以文本形式存在。如果你只会用 cat 和 vim 来查看和编辑,那效率实在是太低了。
好在 Linux 为我们准备了三位“剑客”——grep、sed、awk。它们各怀绝技,组合起来能解决 90% 以上的文本处理问题:
- grep:负责查找——从海量文本中快速筛选出你想要的线索
- sed:负责编辑——批量替换、删除、插入,不改动原文件也能预览效果
- awk:负责格式化与统计——把文本当表格处理,提取列、做计算、生成报表
无论你是运维、开发还是数据分析师,掌握这三剑客,你的工作效率至少翻三倍。本文将从零开始,用最通俗的语言 + 大量实操案例,带你彻底吃透它们。
💡 阅读建议:打开你的 Linux 终端,边看边敲,动手才是最快的学方式。
一、准备工作:搭建实验环境
在学习之前,我们先创建一个测试文件,后面所有命令都基于它来练习。
# 创建工作目录 mkdir -p ~/three-musketeers cd ~/three-musketeers # 创建示例日志文件 cat > sample.log << 'EOF' 2025-05-24 10:00:01 INFO Starting MySQL master 2025-05-24 10:05:12 WARN Connection slow from 192.168.1.10 2025-05-24 10:10:45 ERROR Failed to replicate to slave1 2025-05-24 10:15:33 INFO Cleaning up old backups 2025-05-24 10:20:18 ERROR Connection timeout to slave2 2025-05-24 10:25:55 WARN Disk usage over 80% 2025-05-24 10:30:22 INFO Backup completed successfully EOF
# 检查三剑客是否已安装(一般系统都自带)
for cmd in grep sed awk; do
command -v $cmd > /dev/null 2>&1 && echo "✅ $cmd 已安装" || echo "❌ $cmd 未安装"
done二、grep:文本搜索的“探照灯”
grep 的名字来源于 ed 编辑器中的命令 g/re/p(globally search a regular expression and print)。它的核心功能就一句话:在文件或输入中,找出所有包含指定模式的行并打印出来。
2.1 基本语法
grep [选项] '搜索模式' [文件...]
2.2 常用选项速查表
| 选项 | 作用 | 使用频率 |
|---|---|---|
-i | 忽略大小写 | ⭐⭐⭐⭐⭐ |
-v | 反向匹配(显示不包含模式的行) | ⭐⭐⭐⭐⭐ |
-n | 显示行号 | ⭐⭐⭐⭐ |
-c | 只计数(显示匹配的行数,不显示内容) | ⭐⭐⭐⭐ |
-r 或 -R | 递归搜索目录下的所有文件 | ⭐⭐⭐⭐ |
-w | 整词匹配(只匹配完整单词) | ⭐⭐⭐ |
-l | 只显示包含匹配内容的文件名 | ⭐⭐⭐ |
-E | 使用扩展正则表达式(支持 +、?、` | ` 等) |
-A n | 显示匹配行及其后 n 行 | ⭐⭐ |
-B n | 显示匹配行及其前 n 行 | ⭐⭐ |
-C n | 显示匹配行及其前后各 n 行 | ⭐⭐ |
2.3 基础用法(从最简单开始)
① 精确搜索:查找包含 “ERROR” 的行
grep "ERROR" sample.log
输出:
2025-05-24 10:10:45 ERROR Failed to replicate to slave1 2025-05-24 10:20:18 ERROR Connection timeout to slave2
② 忽略大小写:查找 “error”(不区分大小写)
grep -i "error" sample.log
③ 显示行号:定位问题更快
grep -n "ERROR" sample.log
输出:
3:2025-05-24 10:10:45 ERROR Failed to replicate to slave1 5:2025-05-24 10:20:18 ERROR Connection timeout to slave2
④ 反向查找:找出所有不是 INFO 的行
grep -v "INFO" sample.log
⑤ 只计数:统计 ERROR 出现了几次
grep -c "ERROR" sample.log # 输出: 2
2.4 正则表达式:让 grep 真正强大起来
正则表达式是 grep 的灵魂。掌握下面这几个元字符,就能解决 80% 的搜索需求:
| 元字符 | 含义 | 示例 |
|---|---|---|
^ | 匹配行首 | ^ERROR 匹配以 ERROR 开头的行 |
$ | 匹配行尾 | completed$ 匹配以 completed 结尾的行 |
. | 匹配任意单个字符(除换行符) | r..t 匹配 root、r00t、r2t 等 |
* | 前一个字符出现 0 次或多次 | ro*t 匹配 rt、rot、root、rooot |
[] | 匹配括号内任意一个字符 | [0-9] 匹配任意数字 |
[^] | 匹配不在括号内的任意字符 | [^0-9] 匹配非数字字符 |
\ | 转义字符,匹配特殊符号本身 | \. 匹配点号 . |
实操案例:
# 1. 查找以 ERROR 开头的行
grep "^ERROR" sample.log
# 2. 查找以数字结尾的行
grep "[0-9]$" sample.log
# 3. 查找包含 IP 地址的行(192.168.x.x)
grep "192\.168\.[0-9]\{1,3\}\.[0-9]\{1,3\}" sample.log
# 输出: 2025-05-24 10:05:12 WARN Connection slow from 192.168.1.10
# 4. 查找空行(在配置文件中很有用)
grep "^$" /etc/ssh/sshd_config
# 5. 查找非注释行(排除以 # 开头的行)
grep -v "^#" /etc/ssh/sshd_config2.5 实战场景:日志排查三板斧
场景一:查看最近一小时的错误日志
# 计算一小时前的时间
START_TIME=$(date -d '1 hour ago' +"%Y-%m-%d %H:%M")
grep "${START_TIME:0:13}" sample.log | grep "ERROR"场景二:找出包含 ERROR 或 WARN 的所有行
# 使用 -E 启用扩展正则,| 表示“或” grep -E "ERROR|WARN" sample.log
场景三:在大量日志文件中递归搜索
# 在 /var/log/ 目录下所有文件中搜索 "Failed" grep -r "Failed" /var/log/
三、sed:流式编辑的“手术刀”
如果说 grep 是“找”,那 sed 就是“改”。sed(Stream EDitor)是一个非交互式的流编辑器——它逐行读取文本,根据规则处理每一行,然后把结果输出。默认情况下,sed 不会修改原文件,这让你可以放心预览效果。
3.1 基本语法
sed [选项] '地址 命令' 文件名
- 地址:指定要操作哪些行(行号、范围、或正则匹配)。省略则作用于所有行。
- 命令:要执行的操作(替换
s、删除d、打印p等)。
3.2 核心命令速查表
| 命令 | 全称 | 作用 |
|---|---|---|
s/old/new/ | substitute | 替换文本 |
d | delete | 删除行 |
p | 打印行(常与 -n 配合) | |
a\ | append | 在指定行之后追加文本 |
i\ | insert | 在指定行之前插入文本 |
c\ | change | 替换整行内容 |
3.3 替换操作(最常用)
① 基本替换:把第一个 “INFO” 替换为 “NOTICE”
sed 's/INFO/NOTICE/' sample.log
⚠️ 注意:默认只替换每行第一个匹配项。
② 全局替换:把所有 “INFO” 都替换为 “NOTICE”
sed 's/INFO/NOTICE/g' sample.log
③ 替换并直接修改文件(-i 选项)
# 先备份再修改(-i.bak 会生成 .bak 备份文件) sed -i.bak 's/WARN/WARNING/g' sample.log
⚠️ 危险操作警告:
-i会直接修改原文件,建议永远先做备份!
④ 只替换特定行:只修改第 3 行的内容
sed '3s/ERROR/CRITICAL/' sample.log
⑤ 按行号范围替换:修改第 2 到第 4 行
sed '2,4s/WARN/WARNING/' sample.log
⑥ 按正则匹配替换:只修改包含 “ERROR” 的行
sed '/ERROR/s/Failed/FATAL/' sample.log
3.4 删除操作
# 删除第 3 行 sed '3d' sample.log # 删除第 2 到第 4 行 sed '2,4d' sample.log # 删除所有包含 "INFO" 的行 sed '/INFO/d' sample.log # 删除所有空行 sed '/^$/d' sample.log # 删除所有注释行(以 # 开头的行) sed '/^#/d' /etc/ssh/sshd_config
3.5 打印与查看
# 只打印第 3 行(-n 禁止默认输出) sed -n '3p' sample.log # 只打印包含 "ERROR" 的行(相当于 grep) sed -n '/ERROR/p' sample.log # 打印第 2 到第 5 行 sed -n '2,5p' sample.log
3.6 插入与追加
# 在第 3 行之前插入一行 sed '3i\This is a new line' sample.log # 在第 3 行之后追加一行 sed '3a\This is a new line' sample.log # 在文件开头插入 sed '1i\# This is a header' sample.log # 在文件末尾追加 sed '$a\# This is a footer' sample.log
3.7 实战场景:批量修改配置文件
场景一:批量替换配置文件中的 IP 地址
# 将配置文件中的所有 192.168.1. 替换为 10.0.0. sed -i 's/192\.168\.1\./10.0.0./g' /etc/myapp/config.conf
场景二:批量注释掉配置项
# 在包含 "AllowUsers" 的行首加上 #(注释掉) sed -i '/AllowUsers/s/^/#/' /etc/ssh/sshd_config
场景三:删除日志中的敏感信息
# 将 IP 地址替换为 [REDACTED]
sed -E 's/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[REDACTED]/g' access.log场景四:多命令组合执行
# 先删除空行,再把所有 "old" 替换为 "new" sed -e '/^$/d' -e 's/old/new/g' file.txt
四、awk:格式化与统计的“瑞士军刀”
如果说 grep 是“找”,sed 是“改”,那 awk 就是“算”——它天生擅长处理按列(字段)分布的数据,就像一个命令行版的 Excel。
awk 的名字来自三位创始人 Aho、Weinberger、Kernighan 的姓氏首字母。它不仅仅是一个命令,更是一门完整的编程语言,支持变量、数组、条件判断、循环等。
4.1 基本语法
awk '模式 { 动作 }' 文件名- 模式(Pattern) :可选,决定是否执行动作(正则匹配、条件判断等)
- 动作(Action) :必选,用
{}括起来,对匹配的行执行操作
4.2 核心概念:记录与字段
awk 把输入按行分割,每一行称为一个 记录(Record) ;每行再按分隔符切分成多个 字段(Field) 。
| 概念 | 说明 | 引用方式 |
|---|---|---|
| 整行 | 当前记录 | $0 |
| 第 1 个字段 | 第一列 | $1 |
| 第 2 个字段 | 第二列 | $2 |
| … | … | … |
| 最后一个字段 | 最后一列 | $NF |
4.3 内置变量速查表
| 变量 | 含义 |
|---|---|
NR | 当前行号(Number of Records) |
NF | 当前行的字段总数(Number of Fields) |
FS | 输入字段分隔符(默认为空格/制表符) |
OFS | 输出字段分隔符(默认为空格) |
RS | 输入记录分隔符(默认为换行符) |
FILENAME | 当前文件名 |
4.4 基础用法(从最简单的开始)
① 打印整行:相当于 cat
awk '{print $0}' sample.log② 打印指定列:打印第一列(时间)和第三列(日志级别)
awk '{print $1, $3}' sample.log输出:
2025-05-24 INFO 2025-05-24 WARN 2025-05-24 ERROR ...
③ 自定义分隔符:处理 /etc/passwd 这类以冒号分隔的文件
awk -F: '{print $1, $3}' /etc/passwd
# -F: 指定冒号为分隔符,打印用户名和 UID④ 条件过滤:只打印 ERROR 级别的日志
awk '$3 == "ERROR" {print $0}' sample.log⑤ 数值条件:打印 UID 大于 1000 的用户
awk -F: '$3 > 1000 {print $1}' /etc/passwd4.5 BEGIN 和 END:预处理与收尾
BEGIN:在处理任何行之前执行(适合初始化)END:在所有行处理完成之后执行(适合汇总统计)
# 统计文件总行数
awk 'END {print "Total lines:", NR}' sample.log
# 输出: Total lines: 7
# 统计 ERROR 出现的次数
awk '/ERROR/ {count++} END {print "ERROR count:", count}' sample.log
# 输出: ERROR count: 24.6 高级功能:这才是 awk 的真正威力
① 分组统计(关联数组)
统计每种日志级别各出现多少次:
awk '{count[$3]++} END {for(level in count) print level, count[level]}' sample.log输出:
INFO 3 WARN 2 ERROR 2
② 计算平均值
# 假设有一个包含数字的文件
cat > numbers.txt << EOF
10
20
30
40
50
EOF
awk '{sum += $1; count++} END {print "Average:", sum/count}' numbers.txt
# 输出: Average: 30③ 格式化输出:自定义分隔符
awk 'BEGIN{OFS=" | "} {print $1, $3, $5}' sample.log④ 提取特定模式的字段
# 提取日志中的 IP 地址(假设在第 5 列)
awk '{print $5}' sample.log | grep -E "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"4.7 实战场景:日志分析与报表生成
场景一:统计 Nginx 访问日志中各状态码的数量
awk '{status[$9]++} END {for(s in status) print s, status[s]}' access.log场景二:找出访问量最高的前 5 个 IP
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -5场景三:计算接口平均响应时间
# 假设日志格式:时间 IP 接口 响应时间(ms)
awk '{sum += $4; count++} END {print "Average response time:", sum/count "ms"}' api.log五、三剑客联合作战:1+1+1 > 3
三剑客真正的威力在于通过管道符 | 组合使用。每个命令做好自己最擅长的事,串联起来就能完成复杂任务。
5.1 经典组合案例
① 查找并统计错误
# 查找所有 ERROR 行,再统计数量 grep "ERROR" sample.log | wc -l # 或者直接用 grep -c grep -c "ERROR" sample.log
② 提取特定字段并排序去重
# 从日志中提取所有 IP,排序后去重计数
awk '{print $5}' sample.log | sort | uniq -c | sort -nr③ 查找并替换(grep + sed)
# 找出包含 "ERROR" 的行,再把 "ERROR" 替换为 "CRITICAL" grep "ERROR" sample.log | sed 's/ERROR/CRITICAL/g'
④ 三剑客联手:分析日志生成报表
# 从日志中提取 ERROR 行,提取时间列,再统计各小时错误数
grep "ERROR" sample.log | awk '{print $2}' | cut -d: -f1 | sort | uniq -c5.2 真实运维场景:分析 Web 日志
# 需求:从 access.log 中找出 404 错误最多的前 10 个 URL
awk '$9 == 404 {print $7}' access.log | sort | uniq -c | sort -nr | head -10
# 拆解:
# awk '$9 == 404 {print $7}' → 提取状态码为404的请求URL(第7列)
# sort → 排序
# uniq -c → 去重并计数
# sort -nr → 按次数降序排列
# head -10 → 取前10名六、三剑客对比总结
| 维度 | grep | sed | awk |
|---|---|---|---|
| 核心定位 | 查找 | 编辑 | 格式化与统计 |
| 擅长领域 | 按行搜索匹配 | 批量替换、删除、插入 | 按列处理、计算、生成报表 |
| 是否修改文件 | 不修改 | 默认不修改(-i 可修改) | 不修改 |
| 编程能力 | 弱(仅正则匹配) | 中等(支持分支、循环) | 强(完整的编程语言) |
| 学习曲线 | 平缓 | 中等 | 较陡 |
一句话总结:
- 想找东西 → 用 grep
- 想改东西 → 用 sed
- 想算东西 → 用 awk
七、避坑指南
7.1 grep 常见坑
| 问题 | 解决方案 |
|---|---|
搜索特殊字符(如 .、*、$)没有结果 | 用 \ 转义,如 grep "\." |
| 搜索时大小写不匹配 | 加 -i 选项 |
| 想匹配完整单词却匹配了子串 | 加 -w 选项 |
7.2 sed 常见坑
| 问题 | 解决方案 |
|---|---|
sed -i 改坏了文件 | 永远先备份:sed -i.bak |
替换中包含 / 符号 | 换分隔符,如 sed 's#/old/#/new/#g' |
| 修改不生效 | 检查是否用了 -i,或者输出被重定向了 |
7.3 awk 常见坑
| 问题 | 解决方案 |
|---|---|
| 字段分隔符不对 | 用 -F 指定正确分隔符 |
| 变量未初始化 | awk 中未初始化的变量默认为空字符串或 0 |
| 大文件性能问题 | awk 是流式处理,内存占用很小 |
7.4 通用建议
- 先用不带
-i的 sed 预览效果,确认无误后再加-i - 处理重要文件前先备份
- 善用管道符
|,把简单命令组合成强大工具 - 正则表达式在三剑客中通用,学好正则事半功倍
八、总结
通过这篇文章,你已经掌握了:
- ✅ grep:快速搜索文本,配合正则表达式精准定位
- ✅ sed:批量编辑文本,替换、删除、插入一气呵成
- ✅ awk:按列处理数据,统计、计算、生成报表
- ✅ 三剑客联合作战:通过管道组合使用,解决复杂问题
下一步行动:拿起你的键盘,用今天学的命令去处理一份真实的日志文件或配置文件。实践一次,胜过读十遍教程。
如果觉得有用,别忘了收藏和分享,让更多需要的人看到!
本文所有命令已在 CentOS 7/8、Ubuntu 20.04/22.04 环境下验证通过。不同发行版可能略有差异,请以实际环境为准。
到此这篇关于Linux 文本处理三剑客:grep、sed、awk 从入门到精通案例详解的文章就介绍到这了,更多相关linux grep sed awk入门内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
