Day 6-7:文本处理三剑客 —— grep、sed、awk
学前提醒学完今天的内容你再也不用一行行翻日志了。三条命令就能从几千行文本里捞出你想要的东西就像用遥控器搜台一样快。先搞懂三剑客到底是干嘛的用大白话比喻工具一句话理解类比grep从一堆文字里找出包含某个词的行像 CtrlF 搜索但强大 100 倍sed对文字做批量替换或增删像 Word 的查找替换但可以一次改几百个文件awk把文字按列拆开做统计计算像 Excel 的自动分列 公式但能处理几十万行工作流关系记住这个流水线原始文本 → grep 筛出需要的行 → awk 拆列提取 → sed 格式美化 → 输出结果第一部分grep —— 搜索猎犬第1步到第7步第1步grep 是干什么的grep 的全称Global Regular Expression Print全局正则表达式打印。你不用记全称记住一句话grep 能从文件或命令输出里捞出包含指定文字的行。通俗类比把 grep 想象成一只搜救犬你跟它说找 error它冲进日志文件里把所有带 error 的行叼出来给你。第2步最基础的用法打开终端Terminal输入以下命令试试# 在系统日志文件里搜索包含 error 的行 grep error /var/log/syslog # 在用户信息文件里搜索包含 root 的行 grep root /etc/passwd格式拆解grep 要搜的文字 文件路径 ↑ ↑ ↑ 命令 搜索关键词 在哪个文件里搜第3步6个必会选项背下来以后天天用先在终端里创建一个测试文件来练习。跟着下面步骤敲第3-1步创建测试文件# 用 echo 把几行文字写进 test.txt 文件 echo Error: Disk full test.txt # 表示覆盖写入 echo Warning: CPU high test.txt # 表示追加写入 echo DEBUG: all normal test.txt echo error: memory leak test.txt echo INFO: service started test.txt第3-2步逐个测试选项# ① -i忽略大小写error 和 Error 都能搜到 grep -i error test.txt # ② -v反向匹配排除包含 debug 的行 grep -v DEBUG test.txt # ③ -n显示行号方便定位 grep -n error test.txt # ④ -c只统计匹配行数不显示内容 grep -c error test.txt # ⑤ -r递归搜索整个文件夹 # 比如搜索当前目录下所有文件里包含 TODO 的行 grep -r TODO ./ # ⑥ -C显示匹配行前后各几行-C 3 前后各3行 grep -C 2 error test.txt选项作用什么时候用-i忽略大小写不确定关键词大小写时-v排除匹配行过滤掉干扰信息如去掉 debug 日志-n显示行号需要定位到具体哪一行时-c只统计数量只想知道出现了多少次-r搜整个文件夹不知道关键词在哪个文件里-C N看上下文-C 3 前后各3行理解报错来龙去脉⚠️新手陷阱-r 和 -R 基本一样但在遇到符号链接快捷方式时有细微差别。初学阶段先用 -r。第4步grep 的重头戏——正则表达式什么是正则表达式一种描述文字模式的语言。比如以192.168开头的IP地址用正则写成 ^192\.168——这种表达方式就叫正则。你不需要全懂先把下面 6 个最常用的学会就行。第4-1步6个必须记住的符号符号意思例子解释^行开头grep ^root /etc/passwd以 root 开头的行$行结尾grep bash$ /etc/passwd以 bash 结尾的行.任意一个字符grep h.llo匹配 hello、hxllo.*任意内容0到多个字符grep start.*endstart 和 end 之间随便什么[0-9]一个数字grep [0-9] test.txt包含数字的行或者要加 -Egrep -E error第4-2步实战——找出以 192.168 开头的 IP 地址# 192.168 开头的行 grep ^192\.168 /var/log/auth.log⚠️关键细节192\.168 里的反斜杠 \ 是转义符。不加 \ 的话. 会被当成任意字符可能把 192x168 也匹配进来。所以 IP 地址里的点号都写成 \.。第5步grep 管道 终极武器管道 | 的通俗理解把左边命令的输出喂给右边命令当输入。像工厂流水线——上一步的产物直接传到下一步加工。# 第5-1步查看所有进程只显示包含 nginx 的 ps aux | grep nginx # ↑ 管道符号把 ps aux 的输出送给 grep # 第5-2步查看历史命令里有没有用过的 ssh history | grep ssh # 第5-3步链式过滤——先找包含 fail 的行再排除 ignored cat /var/log/syslog | grep -i fail | grep -v ignored # ↑ 第一道过滤 ↑ 第二道过滤第6步grep 综合练习跟着敲一遍# 练习1查看系统里所有 root 用户启动的进程 ps aux | grep ^root # 练习2检查 /etc/passwd 里有多少个用户用 bash 作为默认 shell grep -c bash /etc/passwd # 练习3在当前目录所有 .txt 文件里搜索 TODO显示行号 grep -n -r TODO ./ # 练习4查看系统日志里最近5条含 error 的记录带上下文 grep -i -C 2 error /var/log/syslog | tail -5第7步grep 小结你学会了命令基础搜索grep 关键词 文件忽略大小写grep -i error 文件排除干扰grep -v debug 文件管道组合ps aux | grep nginx正则匹配grep -E error|fatal 文件第二部分sed —— 批量替换大师第8步到第13步第8步sed 是干什么的sed 的全称Stream Editor流编辑器。核心思路一行一行读进来 → 按你给的规则处理 → 输出。它最擅长的是非交互式编辑——尤其在脚本里批量改文件不用像 vim 那样手动打开逐个改。通俗类比sed 就像一个自动盖章机。你把一叠纸文本行塞进去告诉它看到 old 就盖成 new它自动一张张处理完吐出来。第9步最核心功能——替换 s///命令格式sed s/旧内容/新内容/标志 文件名 ↑ ↑ s substitute g/i 等标志 替换的意思第9-1步跟着敲# 基本替换把 world 换成 Linux只替换每行第一个出现的 echo hello world | sed s/world/Linux/ # 输出hello Linux # g 标志替换整行所有匹配global echo ha ha ha | sed s/ha/he/g # 输出he he he # i 标志忽略大小写 echo Hello HELLO | sed s/hello/hi/gi # 输出hi hi # 多标志组合gi global ignore case sed s/old/new/gi file.txt标志含义不加会怎样gglobal全局替换这一行里所有匹配每行只替换第一个iignore case忽略大小写大小写不匹配就不替换不写每行只改第一个—⚠️新手最容易错忘记加 g 标志结果只替换了每行第一个匹配后面的都没动。第10步真正写入文件——-i 选项小心默认情况下 sed只把结果打印到屏幕上不会动原文件。加上 -i 才会真正修改文件。第10-1步养成好习惯——先备份再改# ✅ 正确做法-i.bak 会先生成备份文件 config.ini.bak再修改原文件 sed -i.bak s/Password/Password123456/g config.ini # 验证备份是否生成 ls config.ini* # 应该看到 config.ini 和 config.ini.bak# ❌ 危险做法直接 -i 不备份改坏了就完了 sed -i s/debug/release/g Makefile铁律改配置文件前永远先 cp 原文件 原文件.bak 手动备份或者用 sed -i.bak 自动备份。改崩了执行 cp 原文件.bak 原文件 秒回滚。第11步删除行# 删除第3行 sed 3d file.txt # 删除所有空行^$ 表示行开头紧跟行结尾 空行 sed /^$/d file.txt # 删除所有包含 error 的行 sed /error/d log.txt # 删除第10到第20行 sed 10,20d file.txt第12步打印指定行# 只打印第5行-n 表示不要默认输出所有行 sed -n 5p file.txt # 打印第10到20行 sed -n 10,20p file.txt # 打印从 start 到 end 之间的所有行 sed -n /start/,/end/p file.txt第13步sed 综合实战实战一把 C 代码里的 int 全部替换为 long但不把 print 里的 int 误改掉# \b 是单词边界确保只匹配独立的 int 这个词 sed -i.bak s/\bint\b/long/g my_code.c 不加 \b 的话print 里的 int 也会被替换成 prlong酿成灾难。实战二把配置文件里包含 DEBUG 的那些行中的 printf 改为 fprintf(stderr, ..)# /DEBUG/ 表示只在包含 DEBUG 的行里执行替换 sed -i.bak /DEBUG/s/printf(/fprintf(stderr, /g *.c命令逐段拆解sed -i.bak /DEBUG/ s/printf(/fprintf(stderr, /g *.c ↑ ↑ ↑ ↑ 备份修改 条件:只 替换动作 所有.c文件 匹配含 DEBUG的行第三部分awk —— 文本计算器第14步到第19步第14步awk 是干什么的通俗类比awk 就像把文本扔进一个自动分列的 Excel 表格。它默认用空格/Tab 把每行切成 $1、$2、$3……然后你就可以对每一列做各种操作——打印、判断、加减乘除。awk 名字来源三位作者 Aho、Weinberger、Kernighan 首字母。别想太多记住它是一种列处理语言就行。第15步awk 的核心模型必须理解awk 自动把每行按分隔符默认是空格/Tab切成多列第一列($1) 第二列($2) 第三列($3) ... 整行($0) ↓ ↓ ↓ ↓ root x 0 root:x:0:root:/root:/bin/bash符号含义$1第一列$2第二列$3第三列以此类推$0一整行NR当前是第几行Number of RecordsNF当前行有多少列Number of Fields$NF最后一列因为 NF 是列数$NF 就是最后一列第16步基础用法跟着敲第16-1步创建一个测试文件# 用 echo 创建 data.txt echo 张三 90 85 92 data.txt echo 李四 78 88 80 data.txt echo 王五 95 91 89 data.txt第16-2步基础提取# 打印第一列学生姓名 awk {print $1} data.txt # 输出 # 张三 # 李四 # 王五 # 打印第二列和第三列逗号会自动加空格分隔 awk {print $2, $3} data.txt # 输出 # 90 85 # 78 88 # 95 91 # 打印整行和 cat 一样但可以用来格式化 awk {print $0} data.txt # 打印行号 第一列NR 是内置的行号变量 awk {print NR, $1} data.txt # 输出 # 1 张三 # 2 李四 # 3 王五第16-3步指定分隔符 -F# 默认分隔符是空格。如果文件用冒号分隔如 /etc/passwd就要指定 -F: awk -F: {print $1} /etc/passwd # 打印出所有用户名 把 -F: 理解成告诉 awk这个文件用冒号当分隔符。第17步条件过滤——awk 的 if 能力# 筛选第二列成绩大于 85 的行 awk $2 85 {print $1, $2} data.txt # 输出 # 张三 90 # 王五 95 # 筛选包含error的行且第三列大于500 awk /error/ $3 500 log.txt # 筛选不包含 success 的行 awk !/success/ log.txt第18步计算和统计# 把第二列所有数字加起来 awk {sum $2} END {print 总分: sum} data.txt # ↑ ↑ # 每行都加到sum里 所有行处理完了执行{}里的代码 # 计算平均分 awk {sum $2; count} END {print 平均分: sum/count} data.txt # 打印最后一列$NF 永远等于最后一列 awk {print $NF} data.txtEND 块的解释awk 开始前{...} 每行{...} 结束后{...} 文件 ↑ ↑ ↑ BEGIN块 主处理块 END块最后执行一次第19步格式化输出 printf# %-10s 左对齐占10个字符位置%-5s 左对齐占5个字符位置 awk {printf %-10s %-5s\n, $1, $2} data.txt # 输出整齐美观的表格第四部分三剑客联合作战第20步到第22步真实工作中三条命令是串在一起用的像流水线一样。第20步场景一——分析 Web 日志找出 404 攻击者假设你有一个 access.log格式如下192.168.1.1 - - [17/Jul/2026:10:30:00] GET /index.html HTTP/1.1 200 1024 192.168.1.5 - - [17/Jul/2026:10:31:00] GET /admin HTTP/1.1 404 512任务找出所有 404 请求的 IP统计每个 IP 出现了几次。第20-1步先用 grep 捞出 404 的行grep 404 access.log # 注意 404 前后有空格避免匹配到 4040、1404 等第20-2步再用 awk 提取第1列IP和第7列URLgrep 404 access.log | awk {print $1, $7} # ↑ 输出IP地址 URL第20-3步统计每个 IP 的访问次数grep 404 access.log | awk {print $1} | sort | uniq -c | sort -nr # ↑ 取IP地址 ↑ 排序 ↑ 统计次数 ↑ 按次数倒排管道流程图access.log → grep 404 → awk 取 IP → sort 排序 → uniq -c 计数 → sort -nr 倒排 原始数据 筛选行 提取列 分组准备 统计重复 从多到少第20-4步更高级的写法——纯 awk 一条命令搞定awk $9 404 {print $1, $7} access.log | sort | uniq -c | sort -nr # ↑ 和第20-3步的后半段一样第21步场景二——批量替换 C 项目里的函数任务把项目所有 .c 文件里包含 DEBUG 宏的行中的 printf 全部换成 fprintf(stderr, ..)# 一条命令搞定自动生成 .bak 备份 sed -i.bak /DEBUG/s/printf(/fprintf(stderr, /g *.c命令结构拆解sed -i.bak /DEBUG/ s/printf(/fprintf(stderr, /g *.c ↑ ↑ ↑ ↑ 备份后修改 条件 替换动作 所有 只处理含 把 printf( 换成 .c文件 DEBUG的行 fprintf(stderr,第五部分正则表达式速查表这些是配合三剑客用的万能通配符不需要死记硬背用到的时候回来查就行。表达式含义示例^行的开头^root → 以 root 开头$行的结尾bash$ → 以 bash 结尾.任意一个字符h.llo → hello, hxllo*前面字符重复0到多次lo* → l, lo, loo....*任意内容贪婪a.*b → a开头b结尾的整段[0-9]一个数字[0-9] → 0到9中的一个[a-zA-Z]一个字母[a-zA-Z] → 任意大小写字母|或需 grep -Eerror|fatal → error 或 fatal\b单词边界\bint\b → 只匹配独立单词 int第六部分常见问题速查表问题原因解决方案grep 搜不到内容大小写不一致加 -i 忽略大小写grep 搜不到内容正则特殊字符没转义在 . * [ 前加 \如 192\.168grep 搜不到内容文件是 UTF-8 BOM 编码用 file 文件名 检查编码用 dos2unix 转换sed -i 报错 extra characters at the end of commandmacOS 和 Linux 语法差异Linux: sed -i.bak /macOS: sed -i .bak注意空格awk 输出列错乱分隔符不对用 -F 指定正确分隔符如 -F: 或 -F,awk 输出列错乱内容本身含空格先用 awk {print $0} 看整行长什么样三剑客处理中文乱码终端编码不是 UTF-8执行 export LANGen_US.UTF-8sed 替换含 / 的路径时报错/ 和 sed 的 s/// 冲突改用其他分隔符sed s#/old/path#/new/path#g# 代替 /忘记加 g 标志只替换了第一个sed 默认每行只替换一次加 gsed s/old/new/g第七部分课后作业不要光看不练做完这4道题三剑客才算真正入门。作业1 — grep 基本功# 在 /var/log/auth.log 里找所有包含 Failed password 的行并统计一共出现了多少次 grep Failed password /var/log/auth.log grep -c Failed password /var/log/auth.log作业2 — sed 批量替换# 把当前目录所有 .txt 文件里的 foo 替换为 bar必须生成 .bak 备份 sed -i.bak s/foo/bar/g *.txt作业3 — awk 列提取# 从 /proc/meminfo 中提取 MemTotal 和 MemAvailable 的数值 # /proc/meminfo 格式MemTotal: 16384000 kB # 分隔符是冒号提取第二列 awk -F: /MemTotal|MemAvailable/ {print $1 : $2} /proc/meminfo作业4 — 组合挑战# 查看所有进程按内存占用排序显示前5名的用户名和进程名 ps aux | sort -nr -k4 | head -5 | awk {print $1, $11} # ↑按第4列倒排 ↑取前5行 ↑取第1列(用户)和第11列(进程名)管道拆解ps aux → sort 按内存倒排 → head 取前5 → awk 提取用户名和进程名 列出进程 -nr -k4(第4列) 条记录 $1(第1列) $11(第11列)总结你这两天的收获工具你学会的能力一句话总结grep从海量文本定位目标行在千军万马中取敌将首级sed批量替换、删行、插入让重复劳动消失awk按列切分、统计计算、格式化把文本当 Excel 用**管道 **串联三条命令 这三剑客是 Shell 脚本的核心肌肉。今天打下的基础到了 Day 8-9 学 Shell 脚本编程时会直接爆发。遇到问题别忘了 man grep、man sed、man awk 是永远的后盾。