news 2026/10/10 3:14:52

Linux文本处理三剑客:grep、sed、awk实战详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux文本处理三剑客:grep、sed、awk实战详解

Linux系统常用命令看到第十五篇,说明能坚持读到这里的,多半已经在日常使用中体会到Shell的威力了。这篇聊一个每次讲都能讲出新花样的组合——grep、sed、awk,俗称“文本处理三剑客”。单拎出来每一个都不复杂,但把它们串在一起,就能解决大部分日志分析、配置修改、数据提取的日常需求。这篇会把三者的侧重点、用法细节和组合思路拆开讲一遍,内容相对扎实,建议边看边在终端里试。

1. 三个命令的分工

先统一定位:很多人分不清 grep、sed、awk 到底该用哪一个,其实可以把它们当成三个各司其职的处理器。

grep 是过滤器,只负责从输入里挑出符合条件的行,不做修改。它的核心能力是快速缩小范围,比如从几百MB日志里捞出一批含关键字“error”的行。sed 是编辑器,在不打开文件的情况下对文本做替换、删除、插入等修改,默认不改原文件,而是输出修改后的结果。awk 是分析器,适合处理有结构的文本,特别是空白分隔的表格、日志片段、配置文件片段,它可以按列拆分数据并做求和、计数、条件判断等操作。

用一句话总结:grep 先筛出来,sed 再改一改,awk 最后算一算。

这三个命令的共同基础是正则表达式。理解正则,哪怕只会几个常用符号,也足以应对大多数场景。通配符是Shell层面用的,正则表达式是文本匹配规则,两者别混淆。常用符号包括:点号匹配任意单个字符、星号匹配前一个字符零次或多次、方括号匹配字符集合、脱字符表示行首、美元符表示行尾。

2. 为什么先把范围缩到最小

使用三剑客的第一原则是:能缩小范围就先缩小范围。很多人拿到一个日志文件,不管三七二十一先 awk 一把,然后在里面做一堆匹配,结果表达式写得又长又难维护。实际更高效的做法是先 grep 过滤,再交给 sed 或 awk 处理。比如排查线上故障,第一步一定是快速定位时间窗口,第二步才是提取具体字段。这个习惯比记住任何参数都重要。

再强调一个处理大文件的心法:命令都是流式处理的,数据是一条条流过管道,内存占用非常少。但如果在 awk 之外还要嵌套一堆循环,或者把每行结果存进数组再做多层循环,性能就会明显下降。保持管道简单、步骤清晰,是在处理海量数据时不出乱子的关键。

3. grep 常用操作详解

grep 的使用频率最高,但很多人来来回回只会grep keyword file。其实有几个组合用法值得形成肌肉记忆。

3.1 常用参数组合

最基本的用法是从日志文件里匹配关键字:

grep "error" app.log

实际工作中几乎不会只匹配单个词,通常都会用管道配合。查看包含关键字的同时也显示前后几行,是定位上下文最实用的方法:

grep -n -C 3 "timeout" app.log

-n显示行号,-C 3显示匹配行前后各3行。排查问题的时候很少会看孤零零的一行,往往需要上下文才能判断这个错误是不是致命,所以-C参数建议常用。

如果只要文件清单,不关心具体内容,用-l只列出包含匹配的文件名:

grep -l "password" *.conf

想知道哪些文件不包含某个关键字,用-L。反向排除某个词,用-v,比如想看日志里除了健康检查接口之外的所有请求:

grep -v "/healthz" access.log

多条件同时匹配,可以用-E配合正则。例如匹配两种关键字之一:

grep -E "ERROR|FATAL" app.log

3.2 固定字符串搜索与性能注意

正则表达式虽然方便,但有一个性能陷阱:当搜索超长字符串时,正则引擎需要回溯,速度会变慢。如果关键字里恰好包含点号、星号这些有特殊含义的字符,还容易误匹配。遇到这种情况,加-F参数强制把它当成固定字符串处理,不对特殊语法做解释:

grep -F "auth.token=12345" access.log

固定字符串搜索的速度远快于正则,这在日志量特别大时体感明显。我通常的做法是:先在粗粒度上用-F快速缩小范围,再把结果交给正则做精细处理。

3.3 结合文件通配

grep 可以直接翻目录,不需要先拼接所有文件名:

grep "connection refused" /var/log/nginx/*.log

如果涉及子目录,加上-r递归搜索:

grep -r --include="*.log" "disk full" /var/log

--include限制文件类型,避免误读二进制文件。还嫌慢就用--exclude-dir跳过一些无用的归档目录。

提示:grep a file和cat file | grep a效果一样,但后者多了一个无意义的 cat 进程,文件大了还费内存。直接 grep 就行,这种无意义管道属于同事看了会想优化掉的操作。

4. sed 修改与提取

sed 是流编辑器,一句话解释就是逐行读入、按规则处理、再逐行输出。默认不改文件本身,只有在加了-i参数之后才会修改原文件。理解这个特性非常重要,很多人第一次用 sed 替换后找不到变化,以为是命令没生效,其实是没加-i。

4.1 替换与全局标记

替换是 sed 最常用的功能,基本语法是s/被替换的内容/替换成的内容/。看个配置修改的例子:

sed 's/worker_processes 1/worker_processes 4/' nginx.conf

执行后屏幕会输出修改后的内容,但 nginx.conf 本身没变。确认无误后想真正保存修改:

sed -i 's/worker_processes 1/worker_processes 4/' nginx.conf

注意每行只替换第一个匹配的位置。如果一行里出现多次匹配,必须加全局标记:

sed -i 's/old/new/g' config.txt

g这个字母必须记牢,它是“global”的缩写,意思是一行内全部替换。还有一个高频问题是忽略大小写,在替换命令末尾加i标志即可:

sed -i 's/error/故障/i' app.log

4.2 精确寻址

sed 支持指定要处理的行号或范围,这在修改特定配置片段时非常有用。

只打印第5行到第10行:

sed -n '5,10p' file.txt

-n是关闭默认输出,因为 sed 默认每行都输出,配合p手动打印指定范围内的内容,就是精准提取行段的正确姿势。

删除某个范围内的行:

sed -i '100,200d' large.log

这个用法很适合清理日志中间的无效片段。基于正则寻址更灵活,比如找到“begin”到“end”中间的所有行:

sed -n '/begin/,/end/p' data.txt

4.3 备份习惯

-i直接修改原文件,操作失误就没有后悔药了。养成备份习惯能少踩很多坑:

sed -i.bak 's/old/new/g' app.conf

这样替换前会生成 app.conf.bak,出问题可以直接回滚。批量修改多个文件时也能这样操作。执行替换前先在无-i的情况下跑一遍,把输出重定向到临时文件,用diff对比改动,确认无误后再真正落地:

sed 's/old/new/g' app.conf > /tmp/app.conf.new diff app.conf /tmp/app.conf.new

注意:不要把-i和-n混在一起用于替换场景,-n会抑制输出,导致你无法看到替换结果。验证修改效果时,先单独跑sed不带-i看输出,再决定是否正式落盘。

5. awk 数据提取与统计

awk 严格来说不算命令,而是一门小巧的文本处理语言。它的核心模型是:按行读取,按列拆分,按条件处理。默认按连续空白字符拆分成列,用$1、$2引用第一列、第二列,$0是整行。

5.1 取列与分隔符

从访问日志中提取 IP 和状态码:

awk '{print $1, $9}' access.log

默认分隔符是空白,遇到用逗号或冒号分隔的文件就要用-F指定:

awk -F':' '{print $1}' /etc/passwd

如果是逗号分隔的 CSV,改成-F','。注意输出时默认用空格连接多个字段,想保留原始分隔符效果,可以用OFS变量:

awk -F',' 'BEGIN{OFS=","} {print $1, $2}' data.csv

BEGIN块在 awk 读取文件之前执行,适合设置分隔符和初始化变量,能显著减少重复表达。

5.2 条件过滤与计数

awk 同样支持正则匹配和条件判断。统计 500 错误数量:

awk '$9 == 500 {count++} END {print count}' access.log

END块在所有数据处理完之后执行,适合输出统计结果。这里的count++就是典型的累加操作。

接口响应耗时超过 2 秒的请求数:

awk '$10 > 2 {slow++} END {print slow}' access.log

多条件组合也能直接写:统计 GET 请求且状态码为 200 的数量:

awk '$1 == "GET" && $9 == 200 {cnt++} END {print cnt}' access.log

如果 log 里访问量大的接口需要排行,可以按接口聚合:

awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -10

5.3 数值求和与分组统计

统计响应体总大小:

awk '{sum += $10} END {print sum}' access.log

统计每个接口的请求次数,用关联数组即可:

awk '{cnt[$7]++} END {for (path in cnt) print cnt[path], path}' access.log

数组在 awk 中非常自然,键可以是任意字符串,这正是日志分组统计的高效写法。

5.4 常见误区

awk 的print $1, $2输出字段间默认是空格,不是原始分隔符。在替换或提取时如果发现输出格式变了,这就是原因。解决办法是显式设置OFS。

另一个常见误区是忘记条件表达式与字符串的比较。比如判断第一列是否等于 GET,必须加引号写作$1 == "GET",写成$1 == GET会把 GET 当成变量,得到空值,匹配结果全错。

提示:awk 读取大文件是边读边处理,非常省内存。但如果把每一行都存进数组不设清理机制,例如{a[$1]=$2}这种,在超大文件中内存就可能被拖垮。合理评估数组使用场景,避免全量缓存无界增长。

6. 三个命令的组合实战

单一命令解决不了的问题,组合起来往往就是常规套路。以下三个场景是生产环境里最常见的标准用法。

6.1 日志分析组合套路

场景:从访问日志里找出所有 500 错误,提取出对应请求的 IP 和请求路径,再按 IP 统计次数。

分步执行是这样的:

第一步,先用 grep 过滤出 500 行,缩小范围:

grep " 500 " access.log > /tmp/500.log

第二步,用 awk 提取关键字段,并做 IP 计数:

awk '{cnt[$1]++} END {for (ip in cnt) print cnt[ip], ip}' /tmp/500.log | sort -rn | head -20

这里grep负责粗筛,awk负责精提取与统计,各干各的,逻辑清晰。

如果只是想快速瞄一眼哪些接口出问题最多:

grep " 500 " access.log | awk '{print $7}' | sort | uniq -c | sort -rn

awk '{print $7}'提取出路径列,sort | uniq -c统计每个路径出现次数,sort -rn按次数倒序。这个四连管道用的频率极高,强烈建议背下来。

6.2 配置批量修改组合

批量替换配置文件里某段参数:

grep -rl "MemTotal" /etc/conf.d/ | xargs sed -i 's/oldSetting/newSetting/g'

这里的grep -rl先定位哪些文件包含关键字,只输出文件路径,交给 xargs 传给 sed 做批量替换。相比自己一个个文件手改,效率提升明显,脚本化也更安全。

如果只想替换满足某个条件的行,sed 与 awk 可以交叉使用,例如只修改第200行到第500行之间的配置:

sed -i '200,500s/threads=2/threads=4/' app.conf

6.3 实时查看与过滤

排查问题时经常会持续观察日志的输出,用tail -f配合 grep 实时过滤:

tail -f app.log | grep --line-buffered "ERROR"

--line-buffered参数很关键,没有它 grep 的输出会因为管道缓冲而延迟,导致你无法实时看到新增的日志行。需要实时分析就用tail -f,不需要时就别用,避免长期占用文件句柄。

提示:tail -f+ grep 在生产环境观察日志是标准组合,但要在排查结束时及时用 Ctrl+C 终止。如果不终止,终端会一直占用资源,一些谨慎的自动化平台甚至会因此判定有未退出进程。

7. 实战中的经验与避坑记录

每次写 Linux 命令相关的内容,都会强调几个反复遇到的坑,这三剑客的坑尤其集中。

第一,grep 搜索关键字时,如果关键字带点号或星号,一定要先问自己一句:这个符号是想让它作为正则生效,还是单纯就是个普通字符?如果是普通字符,加-F准没错。曾经有一次排查“订单号.gzip”格式的日志,直接用 grep 匹配出来的结果比实际多了整整一倍,就是漏了-F,把点号当成了任意字符。

第二,sed 的-i在部分环境中行为略有差异,有些版本要求必须显式指定备份后缀。稳妥起见,只要是重要配置文件,一律使用-i.bak方式执行,改错了还有一个兜底。生产环境的配置修改前先备份,这个习惯能救命的次数比想象中多。

第三,awk 里字符串比较一定要加引号。第一次写统计 GET 请求数量的脚本时,因为漏了一个引号,统计结果要么为0,要么等于总行数,逻辑完全乱了套。排查下来发现是变量和字符串混为一谈。从现在起养成习惯:$1 == "GET",引号一定不能省。

第四,同时处理多个文件时,awk 默认会把第一个文件的每一行后面加一个空行,多文件统计时要注意这一点。如果不想要这个行为,可以用FNR==1条件配合nextfile等方式调整。实际使用中我通常会把多个文件先用 cat 拼接成标准输入再交给 awk,避免多文件边界带来的隐藏问题:

cat access.log access.log.1 | awk '{print $1}' | sort | uniq -c

第五,管道命令要有意识地控制数量。四连、五连的管道虽然看着潇洒,但每多一个管道就多一分缓冲开销。小文件无所谓,上百MB的大文件时管道缓冲对性能的影响不再可忽略。可以先落盘中间结果:

awk '{print $7}' access.log > /tmp/urls.txt sort /tmp/urls.txt | uniq -c | sort -rn | head -20

分步执行还有一个好处:每一步结果可视化,排查逻辑出错时更容易定位是哪一步产生了脏数据。

8. 日常高频命令速查

整理成一张速查表,方便贴在终端旁边。不用刻意背,碰到场景来查一次,多用几次就记住了。

目标命令
快速查找关键字并显示行号grep -n "key" file
排除含关键字的行grep -v "key" file
同时匹配多个模式grep -E "err1|err2" file
显示匹配前后各3行上下文grep -C 3 "key" file
只列含关键字的文件名grep -l "key" *.conf
固定字符串匹配(不用正则)grep -F "1.2.3" file
无备份替换某关键字sed -i 's/old/new/g' file
带备份替换(推荐)sed -i.bak 's/old/new/g' file
打印第5到10行sed -n '5,10p' file
删除第100到200行sed -i '100,200d' file
按冒号切分取第一列awk -F':' '{print $1}' file
统计总行数awk 'END{print NR}' file
按第一列分组统计次数awk '{c[$1]++} END{for(k in c) print c[k],k}' file
统计数字列总和awk '{s+=$1} END{print s}' file

速查表里不少组合其实是互相关联的,单独记参数难,配合实战场景去记就轻松得多。比如表格里的分组统计,本质上就是“先拆列,再入数组,最后遍历输出”三步走。把整个套路想明白,参数自然忘不了。

我个人平时用得最多的是先grep快速定位异常,再用awk提取字段并统计分布,必要时用sed做临时性修改,三者的边界清晰,组合起来基本不重样。工具的魅力不在于背下所有参数,而在于面对具体问题时能迅速找到正确的组合方式。这也是为什么文本处理能力永远是 Linux 使用者的基本功:不管上层技术怎么变,日志还是那些日志,文本还是那些文本,会处理文本的人永远多一张底牌。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 3:14:49

transformer架构的学习笔记

学习参考视频:【Transformer 算法原理与实战】https://www.bilibili.com/video/BV1ej1EBWEWu?vd_source885c958fed22b3aa519cf675b9bbe233 up 主:炮哥带你学。 对比了几个课程,感觉这套 Transformer 课程直击重点,对新手友好&am…

作者头像 李华
网站建设 2026/10/10 3:14:34

VMware Tools 8.8.0离线安装指南:老内核Linux虚拟机必备内核模块方案

简介:本资源为VMware Tools 8.8.0正式版安装包(构建号471268),面向Linux/Unix虚拟机用户及VMware平台运维人员,专用于提升虚拟机性能、图形渲染、I/O效率与宿主协同能力。压缩包含2477个文件,主体为1598个编…

作者头像 李华
网站建设 2026/10/10 3:14:32

轻量级前端知识竞赛系统:离线可用、实时排名、自动判分

简介:这是一套基于VC6.0开发的C知识竞赛系统完整源码工程,面向高校计算机专业学生、课程设计实践者及C初学者,解决在线答题、题库管理与实时排名等典型教学类竞赛场景需求。资源包含61个文件,涵盖11个cpp核心逻辑模块(…

作者头像 李华
网站建设 2026/10/10 3:14:28

策略模式实战:从订单计价if-else重构到设计模式落地

1. 项目概述:从一次订单计价重构说起策略模式这个名词,干过一段时间后端的应该都不陌生。打开IDE搜一下,规模稍微大一点的工程里基本都能看到一堆以Strategy结尾的类。这篇是这个设计模式系列的第五篇,我们专门来聊策略模式。我会…

作者头像 李华
网站建设 2026/10/10 3:14:23

华为MetaERP一套科目,三种视角经营科目表 × 集团科目表 × 备选科目表(中国) —— 编码设计哲学、实现逻辑与底层原理一、先看事实:三个号码不是乱编的你给出的三个编码,长度不同、结构不同

一套科目,三种视角经营科目表 集团科目表 备选科目表(中国) —— 编码设计哲学、实现逻辑与底层原理一、先看事实:三个号码不是乱编的你给出的三个编码,长度不同、结构不同、用途不同。这不是"同一个科目的三个…

作者头像 李华
网站建设 2026/10/10 3:14:14

Flutter on OpenHarmony 数据持久化实战:电子合同场景选型与踩坑

从第一次在模拟器上把Flutter应用跑进OpenHarmony,到真正把完整的电子合同签署App落地,最折磨人的其实不是UI适配,反而是那些看起来没什么技术含量的数据持久化。我最初想得很简单:数据库存一下合同内容,本地存一下PDF…

作者头像 李华