Linux文本处理三剑客精讲:grep、sed、awk实战指南

发布时间:2026/10/21 5:47:37
Linux文本处理三剑客精讲:grep、sed、awk实战指南 从Liunx这个拼写说起。说实话我第一次看到这个标题的时候也愣了一下随即又觉得亲切——这不就是当年我们刚接触Linux时常见的状态吗一边敲着命令一边搜着教程连系统名字都还没拼利索。不过拼写归拼写这个系列能一路写到第八篇说明读者是真在跟着上手练。前面几篇我们先后折腾过虚拟机安装、目录结构与文件操作、用户权限、进程与服务、网络基础、磁盘管理今天进入一个更贴近日常运维与自动化脚本的主题文本处理三剑客。为什么是文本处理因为Linux世界里一切皆文件这句话落到实际操作上往往就是一切皆是文本。日志是文本配置是文本命令输出是文本接口返回也是文本。无论你是做服务器运维、数据分析、程序开发还是写自动化脚本每天都要跟文本打交道。而grep、sed、awk这三个工具就是Linux下处理文本最重要的三件武器也是从会敲命令走向会写脚本的分水岭。这篇教程我准备拿一个贯穿全文的案例来讲模拟一份Web服务器的访问日志从里面筛选异常请求、提取关键字段、统计分布、生成格式化报表。跟着做完这一套你就知道三剑客到底分别在干什么活以及它们之间是怎么配合的。1. 为什么文本处理在Linux学习里这么重要1.1 日志和配置文件是绕不开的日常不管你用Linux干什么日志都是第一手情报来源。系统出故障了要看**/var/log/messages或者/var/log/syslog**Web服务出问题了要看访问日志和错误日志应用跑挂了要看业务日志。这些日志的体量往往非常惊人一个中等流量的Web服务一天的访问日志轻松上百万行。你不可能拿着编辑器从头翻到尾唯一的办法就是用命令去筛选、提取、统计。再说配置文件。Linux下几乎每个服务都靠文本配置sshd_config、nginx.conf、my.cnf改一处就要排查一处。这些文件动辄几百行里面全是注释和可选配置用眼睛找效率太低用grep定位才是正经方式。1.2 文本处理是自动化的地基如果只是手动敲命令crond定时任务、异常告警、日志归档、数据清洗这些自动化场景全都做不了。因为脚本的本质就是拿命令的输出当输入再交给下一个命令处理这就是管道符|的威力。而管道的两端往往是文本处理器。我见过不少学Linux的人文件操作和权限管理学得挺熟一到抓日志、写统计脚本就卡住本质上就是因为文本处理这块没有建立起系统的认知。这篇的内容能补上这个短板。1.3 我们这篇要处理的原始数据长什么样为了让后面的操作不抽象我先把贯穿全篇的示例文件准备好。这是一份模拟的Web服务访问日志我给它起名access.log大致长这样2025-11-01 08:12:33 192.168.1.101 GET /api/user/info 200 0.045 2025-11-01 08:12:35 10.0.0.23 POST /api/login 500 1.203 2025-11-01 08:12:37 192.168.1.101 GET /index.html 200 0.012 2025-11-01 08:12:40 172.16.8.9 GET /api/order/list 304 0.021 2025-11-01 08:12:42 10.0.0.23 POST /api/pay 500 2.145每一行的时间、来源IP、请求方法、请求路径、状态码、响应耗时都用空格分隔。这个格式是模仿主流Web服务的访问日志实际上Nginx的默认格式会复杂很多字段更多但这里刻意简化方便理解逻辑。后面你会发现搞清楚每个字段是什么比记住命令更重要。2. grep在一堆文本里快速捞针2.1 最基本的使用方式grep的任务很简单在文件里搜索匹配的行然后把它们打印出来。最基本的用法就是grep 关键词 文件名。比如我想看日志里所有状态码为500的行也就是出错的请求grep 500 access.log输出会把所有包含500的行整行列出来。你会发现这里有个隐患如果某个IP地址或者路径里也包含500这三个字符也会被误匹配进来。这就是初学grep最容易踩的坑——grep匹配的是子串不是单词。想要精确匹配办法是用正则表达式的边界符。后面会展开讲这里先记住grep -w 500 access.log-w表示只匹配整个单词这样500abc这种就不会被捞出来。2.2 常用选项一次讲清在实际操作里我90%的时间用的grep选项就这几个我整理成了个速查表方便你记忆选项作用使用场景-i忽略大小写匹配Error、ERROR、error时-n显示行号在脚本或配置文件里找行号-v反向匹配取反过滤掉注释行、排除某个关键词-c只统计匹配行数快速算日志里某种错误出现了多少次-o只输出匹配的部分提取IP地址、URL等子串-A 3附带匹配行之后3行看异常日志附近的上下文-B 2附带匹配行之前2行看异常发生前的上下文-C 2前后各2行最常用的上下文查看举个例子如果你排查一条报错光看报错行本身往往看不出原因得看它周围的上下文grep -n -C 2 Traceback app.log这个命令会输出匹配行以及它前2行和后2行并且带上行号。排查程序崩溃时我几乎必用。2.3 正则表达式从普通搜索到模糊搜索正则表达式是grep的核心也是很多初学者觉得难的地方。其实不要被这个名字吓到你可以把它理解成一种带通配符的高级搜索方式。它在普通关键词之外加入了对一类字符和数量的描述。举个例子我要在日志中筛选出所有IP地址。一个IPv4地址是四段数字每段1到3位用点号连接。写成正则大约是grep -o [0-9]\.[0-9]\.[0-9]\.[0-9] access.log这里[0-9]代表数字字符表示前面的字符出现一次或多次\.是转义后的点号因为点号在正则有特殊含义必须转义才能匹配字面上的点。但是有个细节要注意grep默认用的是基础正则表达式它不认识这个符号。你得用grep -E相当于egrep才能使用扩展正则语法grep -E -o [0-9]\.[0-9]\.[0-9]\.[0-9] access.log我刚开始学的时候经常在这里栽跟头同样是在主流的编辑器里能用在grep里不加-E就报错或者匹配不到。这个习惯一定要养成学会grep -E少走一半弯路。2.4 小技巧只提取某一段文本-o这个选项很多人忽视但它在提取信息时特别好用。我们后面要统计IP但日志里每行还有其他乱七八糟的内容这时候只需要把IP部分捞出来grep -E -o ([0-9]{1,3}\.){3}[0-9]{1,3} access.log | head -10我先说明一下这个正则([0-9]{1,3}\.){3}表示数字1到3位加一个点这个组合重复三次最后再跟一个1到3位的数字。head -10只是限制只看前10行避免刷屏。到这一步你已经能灵活地从日志里筛出想要的行、抠出想要的字段了。但你会很快遇到一个新的问题很多时候我不只想看还想对文本做修改、删除、替换。这时候sed就该上场了。3. sed不打开编辑器也能改文件3.1 理解sed的流水线工作方式sed的全称是Stream Editor流编辑器。它不像Vim那样打开文件让你交互式操作而是以流的方式工作读一行 - 按你的指令处理 - 输出/写入。你可以把它想象成一条流水线上站着一名工人文件里的每一行经过他面前时他按固定规则做动作——有的行打个标记打印有的行直接扔掉删除有的行改几个字替换。正是因为这个逐行处理的模型sed特别适合处理大文件。不管文件多大内存里始终只装一行稳得很。Vim打开一个上G的日志可能卡到怀疑人生sed一秒钟跑完。3.2 最常用的sed三板斧打印p、删除d、替换s先准备一个简单的测试文件test.txtapple 10 banana 5 orange 8 grape 12打印所有行默认sed就会输出但显式加p参数能帮你理解处理过程sed -n p test.txt这里-n很关键它表示关闭默认输出——因为如果既有默认输出又加p打印每一行会出两次。我建议初学者带上-n去理解你写的是什么。删除第2行sed 2d test.txt替换把apple替换成pearsed s/apple/pear/ test.txts命令是这个工具的绝对主角它的格式固定为s/旧内容/新内容/标志。3.3 替换操作的进阶玩法基础替换只能改第一个匹配到的内容想在每一行把所有的目标都换掉要加g标志sed s/a/A/g test.txt最实用的进阶技巧有两个。第一个是只处理匹配到某个关键词的行比如只把包含orange的行里的8换成88sed /orange/s/8/88/ test.txt这个写法是先限定制行范围再执行替换动作日常改配置时用处极大。第二个是分组引用把匹配到的内容原样拿来再加工。比如把apple 10改成10 apple调换前后两段的位置sed s/\([a-z]*\) \([0-9]*\)/\2 \1/ test.txt\(...\)把匹配到的内容放进组里后面用\1、\2按顺序引用。基础正则要用转义括号用-E就能省去写反斜杠的麻烦。我强烈建议凡是正则内容一律用sed -E或grep -E省心也少出错sed -E s/([a-z]) ([0-9])/\2 \1/ test.txt3.4 把改动写回文件的坑-i参数前面所有操作只是输出到屏幕上并没有真正修改文件。想真正写回文件用-ised -i s/apple/pear/ test.txt注意这里有一个非常经典的大坑。Linux主流发行版默认带的是GNU sed-i后可以直接接命令但macOS自带的BSD sed-i后面必须跟一个参数哪怕不需要备份也要写成一个空字符串# GNU sedLinux写法 sed -i s/apple/pear/ test.txt # BSD sedmacOS写法 sed -i s/apple/pear/ test.txt我当年在一台mac上跑Linux的教程命令结果报错extra characters at the end of d command排查了半天才发现是-i的参数差异。如果你要在生产环境修改重要配置我的习惯是每次都用带备份的方式sed -i.bak s/old/new/ config.ini这样会生成一个config.ini.bak备份文件。改坏了就一条命令还原不至于把配置文件搞崩了手足无措。4. awk把文本当表格一样处理和统计4.1 awk的核心认知一行的字段拆解如果说grep是捞sed是改那awk就是算。awk最擅长的是把每一行按分隔符拆分成若干字段然后逐行处理、统计、汇总。你可以把它想象成一个Excel透视表处理员原文每一行就是一条记录每个字段就是一列。默认情况下awk用空白空格或Tab作为分隔符。对我前面的access.log来说每一行天然就被分成了7个字段。awk用$1表示第一个字段$2表示第二个字段以此类推$0表示整行。先来看最简单的操作打印第1列日期和第7列响应耗时awk {print $1, $7} access.log这时你可能会问怎么和普通文本命令的输出不太一样注意awk的语法结构是条件 {动作}结构——前面是条件后面花括号里是动作不写条件就对所有行执行动作。越早习惯这个模型你学awk越顺畅。4.2 用- F指定分隔符真实世界的日志不少是用逗号或者制表符、竖线分隔的这时候-F参数就派上用场了。我模拟一份CSV风格的数据data.csv2025-11-01,192.168.1.101,GET,200 2025-11-02,10.0.0.23,POST,500按逗号拆列打印第2列IPawk -F , {print $2} data.csv这个技巧在处理导出数据、CSV报表时非常常用。4.3 内置变量NR与NFawk自带一批内置变量其中NR和NF是最常用的两个。NR是当前处理到第几行NF是当前这一行有多少个字段。打印每一行的行号和字段数量awk {print NR, NF} access.log打印最后一列不管这一行有多少列都能准确定位awk {print $NF} access.log这个$NF表示最后一列的写法特别实用因为日志或者表格的格式经常变但你永远关心的是最后一项。我写统计脚本时只要想取响应时间或状态码这类尾字段第一反应就是用$NF。4.4 按条件过滤行awk真正的威力在条件过滤。比如我只想看状态码是500的错误请求的完整行awk $6 500 {print $0} access.log更实用一点筛选出响应耗时超过1秒的慢请求也就是第7列数值大于1的行awk $7 1 {print $0} access.log初学awk时要把和死死分清楚是比较是赋值。我见过不止一个人写条件过滤时用了单等号结果awk没报错但输出结果完全不对因为它在做赋值操作而不是条件判断。4.5 统计功能给日志算一笔账awk的统计能力是它比grep强出一大截的原因。它可以在处理所有行之前做初始化BEGIN处理完所有行之后做输出END。统计状态码500出现了多少次awk $6 500 {count} END {print 500次数:, count} access.log统计所有请求的平均响应耗时awk {sum $7} END {print 平均耗时:, sum/NR} access.log这里sum是一个自定义变量不需要提前声明直接用就行。NR在处理完最后一行时会等于总行数所以sum/NR就是平均值。用这套思路还能做很多事统计某个IP的请求总数、计算某个接口的耗时总和、按小时统计请求量全部是累积 汇总的路子。4.6 更高级的玩法按键值做统计如果只做全量统计距离透析日志还差一步。实际中最常见的需求是分组统计比如统计每个IP访问了多少次。这在awk里可以用一个数组实现awk {ip[$2]} END {for (i in ip) print i, ip[i]} access.log稍微解释一下ip[$2]的意思是以第2列IP作为下标每遇到一个相同的IP计数器就加1。等所有行处理完用for循环把键和值都打印出来。你会发现一个刚装好的Linux发行版就是标准的awk不需要额外装任何软件就能完成很多需要用编程语言才能做的统计工作。5. 三剑客协同从日志到报表的完整实战5.1 实战场景设定在真实环境里三把武器很少单兵作战。我们来做一个完整的小任务从访问日志中统计所有状态码为500的请求按IP统计出现次数找出出错大户最后输出一个排序后的报表。5.2 一步步拆解管道命令第一步先用grep筛出状态码为500的行。注意这里不能用太简单的grep 500因为路径里可能带500。我们结合状态码在行尾这个特征grep -E 500$ access.log$是正则里的结尾锚定这样只有行尾是空格加500的才算数。这比用awk更简单直接没问题但在这篇里为了展示分工我统一用awk来过滤。第二步从这些行里提取IP。我们前面已经知道了awk里$2就是IPawk $6 500 {print $2} access.log第三步在awk里直接做统计并打印awk $6 500 {count[$2]} END {for (ip in count) print ip, count[ip]} access.log第四步按次数从大到小排序。awk输出是乱序的需要用sort配合。sort -rn里的-r是反转从大到小-n是按数值排序不然10会排在2前面因为按字典序10小于2awk $6 500 {count[$2]} END {for (ip in count) print ip, count[ip]} access.log | sort -rn -k 2第五步加上一个标题行顺便生成一份可读性更好的报表。这里用sed来拼接/插入一行也可以用echo然后重定向。我把完整的一条命令写成这样的形式echo IP 错误次数 echo --------------------- awk $6 500 {count[$2]} END {for (ip in count) print ip, count[ip]} access.log | sort -rn -k 25.3 再增加一个需求统计接口的平均耗时实际运维中最常见的任务是找出哪些接口变慢了。我们扩展一下统计每个请求路径第4列的平均响应耗时第7列只关心出现次数超过一定阈值的接口。这里要用到awk的两个数组一个累计耗时一个累计次数awk {sum[$4] $7; cnt[$4]} END {for (path in sum) if (cnt[path] 3) print path, sum[path]/cnt[path]} access.log | sort -k 2 -rn输出结果会是一个按平均耗时排序的接口列表是不是已经有点性能分析报告的意思了5.4 把报表保存成文件在处理完结果后可以用重定向把报表保存下来awk $6 500 {count[$2]} END {for (ip in count) print ip, count[ip]} access.log | sort -rn -k 2 error_report.txt保存下来的文件就能用来发邮件、写值班日报、或者作为脚本的输入继续处理。整个链路就是grep/awk负责筛选和统计sed负责改写文本sort负责排序重定向负责落盘。每个命令各干一摊用管道串起来这就是Linux命令行最舒服的协作方式。6. 实战中的常见坑与我的排查心得6.1 匹配不到内容先怀疑隐藏字符grep搜不到结果很多人的第一反应是关键字写错了。但更常见的原因是文件里的不可见字符在捣乱。比如Windows下编辑的文件每行末尾有一个\r回车符Linux下的命令看不到但实际存在。这种文件你用grep pattern匹配通常会失败因为行尾多了个\r。排查方法很简单用cat -A看一下文件真实内容cat -A access.log | head -5如果看到行尾有^M$说明这就是Windows换行符。用sed清洗一下sed -i s/\r$// access.log这个命令能把行尾的\r删掉。我在处理从别处拷贝过来的脚本、配置文件时遇到各种诡异问题十有八九是换行符和编码。6.2 正则的贪婪特性.* 匹配到的是最后面正则里的.*表示任意字符出现任意多次它在默认情况下是贪婪的会尽量匹配最多的内容。举个例子从一行文本里提取第一个引号之间的内容namealice age20你想提取alice写.*会把alice age20整个匹配出来因为它从第一个引号开始一直吃到最后一个引号才算完。这就是经典的正则贪婪匹配坑。解决办法是用[^]*——意思是匹配除了引号以外的任意字符echo namealice age20 | grep -o [^]*这个细节在解析JSON行、HTML标签、日志参数时经常用到。第一次遇到时可能会困惑半天理解了贪婪机制后就通了。6.3 别什么都用管道先拆开单步验证我知道很多人包括从前的我学完三剑客容易陷入一条命令特别长的炫技模式。把grep、sed、awk、sort、uniq全串在一行里写的时候很爽出错的时候很惨——你不知道到底哪一步出了问题。我的习惯是先单步执行验证每一步的输出确认无误后再拼接起来。写一个管道命令绝不直接一次成型而是像这样一步步来# 第一步先看原始数据有没有过滤对 awk $6 500 {print $2} access.log # 第二步加上统计先看结果长什么样 awk $6 500 {count[$2]} END {for (ip in count) print ip, count[ip]} access.log # 第三步再排序 ... | sort -rn -k 2 # 最后再加上表头和重定向这样做的好处很明显一旦某一步输出不符合预期你立刻知道问题出在这一步而不需要拆掉整条命令去猜。这个排查思路适用于所有命令行组合的调试也是我建议你在初期就养成的工作习惯。6.4 定期用三剑客复盘自己的命令历史最后补充一个我屡试不爽的学习方法在系统上敲的命令都会记录在用户主目录下的历史文件里比如~/.bash_history你每周可以花十分钟去翻一翻看看自己高频使用哪些命令、哪些操作还能被命令替代/简化。比如你发现经常在日志里搜同一个关键字就应该考虑写一个简短的shell函数去封装它。其实文本处理就是这样看着命令不少但真正高频的也就那么几十个。多用几次多踩几次坑它们就会变成肌肉记忆。这篇的内容虽然按grep、sed、awk分开讲但实际干活时三件套是永远连在一起用的你用熟了之后自然会形成一种手感看到一段文本脑子里已经自动在拆解该用什么命令去切它、筛它、算它。下一篇我打算接着这个基础讲Shell脚本的控制结构——条件判断和循环正好把这篇的文本处理能力编排成可复用的脚本。如果你在跟练时有什么有趣的坑欢迎在评论区聊聊互相长点经验。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询