发布时间:2026/9/7 15:25:04
深入理解grep:从基础用法到日志排查实战 “每天一个Linux命令”系列grep这可能是你最常用的排查工具老规矩今天这个系列轮到 grep。我最早接触 Linux 的时候其实不太理解为什么大家天天把 grep 挂在嘴边。直到有次线上服务出问题我需要在几万行日志里定位一条报错在几十个进程里确认某个服务是否还活着在配置文件堆里搜某个参数到底写在哪才发现这玩意几乎是所有排查动作的地基。后来我带新人第一个星期只让他们练三件事grep、管道、vim 看文件。这三件事熟练了Linux 日常操作基本不会卡壳。这篇不打算把 man 手册抄一遍而是按照我自己的使用习惯把 grep 真正高频的用法、组合方式、以及踩过的坑整理出来。无论你是刚入行的运维、写代码的开发、还是准备面试的学生这都应该能成为你顺手就能翻的参考。如果你已经用了很久 grep重点可以看最后两章——自匹配的坑和几个容易被忽略的细节我自己在这上面吃过不少亏。1. grep 命令定位它不是“搜索文件”而是“按模式过滤文本”1.1 从名字理解 grep 的底层逻辑grep 这个名字看着奇怪其实是一个古老缩写g/re/p也就是 global regular expression print全局正则表达式打印。这个名字基本把它做的事情说透了读取输入逐行去匹配正则表达式匹配上的行就打印出来匹配不上的就丢掉。理解“逐行处理”这一点很关键。grep 不是把整个文件一次性读进内存再去翻而是一行一行地读处理完一行就输出一行。这也是为什么 grep 能轻松处理几个 GB 的大日志文件而不至于把内存打满因为它的工作方式决定了内存占用基本是固定的。你可以把它想象成流水线上的安检员每一行文本就是一个人只有符合规则的才放过去其他的直接走旁路。单看文件名可能会以为它只能搜“文件内容”但实际它的输入源有三种直接给定文件名、从标准输入读取、和其他命令用管道拼接。第三种才是它在 Linux 世界里威力最大的用法后面会专门讲。1.2 五个出现频率最高的参数先记这五个就够了grep 的参数很多但日常最常用的基本就是下面这几个我按使用频率排序-i忽略大小写。查错误日志时Error、ERROR、error 都有可能出现不加这个参数很容易漏。-v反向匹配也就是“不含某个关键词的行”相当于排除。-n显示行号查配置、查代码时几乎必用定位全靠它。-c统计匹配行数而不是输出内容本身。想看某个关键字在文件里出现了多少行用它。-w按单词匹配避免“user”把“username”“user_id”也带出来。举个例子排查 Nginx 配置里所有不含注释的行grep -v # /etc/nginx/nginx.conf再比如统计一个日志文件里出现过多少次 Timeoutgrep -c Timeout app.log-c统计的是“行数”而不是“次数”。同一行里 Timeout 出现三次-c也只会计数一次。如果你确实要统计“出现次数”那得用grep -o Timeout app.log | wc -l-o可以把每个匹配内容单独打一行再用wc -l数行数。这个组合在统计 IP 访问次数时特别管用。1.3 上手实例5 分钟把它用起来先别急着啃正则基础搜索就直接上。假设我要在今天所有的日志文件里找一条包含“OutOfMemoryError”的记录grep -n OutOfMemoryError /var/log/app/2024-06-18.log如果当天文件被分割成多个还可以用通配符指定目录下的一批文件grep -n OutOfMemoryError /var/log/app/2024-06-18*.log这一步的输出会自动带上文件名前缀比如/var/log/app/2024-06-18-10.log:42:xxx方便你一眼看出结果落在哪个文件、哪一行。到了这一步grep 的第一层用法你已经会了接下来要进阶的是正则和组合。2. 正则表达式从“按词找”到“按规律找”2.1 基础正则与扩展正则为什么要区分grep 默认使用的是基础正则表达式BRE而egrep或者grep -E使用的是扩展正则表达式ERE。两者的区别不在于谁更“高级”而在于一些元字符需不需要转义。在基础正则里、?、|、{}、()这些字符默认是字面量想让它表达“一个或多个”“可选”“或者”“分组”这些含义必须加上反斜杠。比如a\表示一个或多个 a。在扩展正则里这些符号直接就能用不需要加反斜杠写起来自然更舒服。所以我个人的习惯是只要涉及正则一律用grep -E省得纠结转义。很多人可能觉得默认的 grep 就够了但如果哪天看到一个命令里写着\{2,\}这种写法不要觉得奇怪那就是基础正则下的次数匹配。2.2 高频正则在真实场景里的写法日常最常碰到的正则需求其实很固定我把常用的列出来每个配一个小例子需求正则写法示例说明行首匹配^grep ^# config.conf找出所有注释行行尾匹配$grep error$ app.log找以 error 结尾的行任意单字符.grep a.c file可以匹配 abc、adc、a1c字符集合[abc]、[0-9]、[a-z]grep [0-9]\{4\} a.log或grep -E [0-9]{4} a.log匹配四位数字一个或多个扩展正则grep -E abc file匹配 abc、abbc零个或多个*grep ab*c file匹配 ac、abc、abbc零个或一个?grep -E ab?c file匹配 ac、abc或逻辑|BRE/ ERE分组\(\)BRE/()EREgrep -E (error举个我真实用过的场景。有次排查日志里的异常耗时要找出所有耗时超过 3000 毫秒的请求日志格式类似cost1234ms。用扩展正则写grep -E cost[3-9][0-9]{3,}ms access.log这个表达式的意思很直白[3-9]是千位从 3 到 9[0-9]{3,}是后面至少跟着三位数这样 3000 以上的都会被捞出来。你可能会问 3000 本身呢[3-9][0-9]{3,}对 3000 能匹配上因为千位是 3后面三位 000。如果我还想包含 2000 到 2999就得再加一类规则不过实际排查中很少需要一次把边界算得那么严大范围命中后人工再确认也不迟。2.3 关于引号一个很多新手忽略的坑grep 的模式建议一律用单引号包起来。原因是单引号能让 shell 不对内容做任何展开里面写什么就是什么。双引号则不同如果模式里有$、反引号、反斜杠shell 可能会先解释一遍再传给 grep。比如你想在日志里搜一个包含$字符的变量名grep $PATH env.log如果你用了双引号grep $PATH env.logshell 会先把$PATH展开成环境变量的值那搜的东西就完全不对了。这个坑很隐蔽因为查别的文字时双引号和单引号结果都一样一旦遇到特殊字符就会莫名其妙地搜不到。顺带一提如果你搜的是中文内容在个别老系统上可能出现乱码或搜不到可以试试先export LC_ALLC.UTF-8或export LANGen_US.UTF-8再执行 grep。这个问题在纯英文环境的服务器上很少暴露但一旦遇到多半就是 locale 设置的事。3. 进程管理组合拳ps 管道 grep 和 kill 的完整链路3.1 热词里的“ps -ef | grep java”到底能查出什么几乎所有 Linux 相关的搜索热词里都有ps -ef | grep java它几乎是运维排查进程的默认起手式。先看ps -ef会输出什么UID PID PPID C STIME TTY TIME CMD root 1 0 0 Jun10 ? 00:00:08 /sbin/init root 1234 1 0 Jun10 ? 00:00:00 /usr/sbin/sshd -D appuser 5678 1 99 10:30 ? 00:02:31 java -Xmx2g -jar app.jar列的含义分别是用户、进程 ID、父进程 ID、CPU 占用率、启动时间、终端、累计 CPU 时间、完整命令。很多人说“用ps -ef | grep java查看启动时间”其实STIME列显示的只是启动的日期或时刻默认精度不够高。如果你真想看精确到秒的启动时间更好的方式是用ps -eo pid,lstart,cmd | grep javalstart会显示完整的启动时间比如Thu Jun 18 10:30:21 2024。所以正确的用法组合是ps -eo pid,lstart,cmd | grep java这里我不建议用ps -ef | grep java去查启动时间因为看到的是简化后的时间。先记住这个差异后面排查进程卡的时长时能少绕路。3.2 为什么每次 grep 都会多出一个“自己”用过ps -ef | grep xxx的人应该都见过这种输出root 10086 1 0 10:30 ? 00:00:00 java -jar app.jar root 10112 1 0 10:31 ? 00:00:00 grep --colorauto java第二条明显不是我们要找的进程它是 grep 命令自己的进程。原因其实很简单管道执行时系统会同时启动ps和grep这两个进程然后 grep 在扫描 ps 的输出时输入里包含了它自己的命令行信息因为ps -ef会列出所有进程包括正在运行的 grep 命令本身于是把自己也匹配上了。解决方式有几种最经典的是用字符类ps -ef | grep [j]ava[j]ava能匹配 java但 grep 自己的命令行里写的是[j]ava它不会匹配文本形式的[j]ava只有真正的 java 进程会被列出来。这个小技巧在面试里偶尔会被问到实际用起来也确实干净。另一个更直接的方式是pgrep -f java它是专门为查进程设计的命令天然规避了自匹配问题。但 pgrep 默认只输出 PID想看完整命令还是要ps -fp $(pgrep -f java)或者直接pgrep -af java。两种方式我都用看当时要做什么。3.3 从查询、过滤到 kill 的完整实操搜热词里有一条很典型的操作用ps -e | grep apt列出所有带 apt 字样的进程然后用 kill 命令一一杀死。这个流程本质就是三件套# 第一步找到目标进程 ps -ef | grep [a]pt # 第二步提取出 PID 列 ps -ef | grep [a]pt | awk {print $2} # 第三步把 PID 传给 kill ps -ef | grep [a]pt | awk {print $2} | xargs kill如果确定要大开杀戒最后那个 kill 可以换成kill -9但我个人强烈建议不要一上来就用-9。kill默认发送的是SIGTERM相当于客气地请进程自己收拾东西离开Java 进程能有机会执行关闭钩子、释放端口而kill -9是SIGKILL直接把进程砍了资源不清理文件可能写到一半甚至留下一些孤儿进程和脏数据。我用一个真实事故说明。那时候我图省事对一批批量任务进程执行了kill -9结果其中一个进程正在写一个中间结果文件内容是写到一半的半个 JSON。下游任务读这个文件直接解析失败连锁报了十几个告警。从那以后我的习惯是先kill等三秒看进程还在不在再用kill -9。能用kill解决的绝不上来就-9。还有一个非常容易被忽略的问题用xargs kill之前务必先看一遍 PID 列表确认没有当前正在跑的、不想杀的关键进程。尤其是那种过滤条件比较宽的命令比如grep apt很可能连系统里的aptd守护进程也匹配进去了杀错以后要花更长时间去恢复。4. 日志排查与代码搜索的高级打开方式4.1 递归搜索整个目录怎么搜才不“爆炸”grep -r可以递归搜索目录下所有文件比如在项目代码里找一个函数在哪定义grep -rn getUserInfo src/-r是递归-n是显示行号。这样一条命令就能把整个代码库里所有相关位置列出来。但问题来了如果目录里有node_modules、.git、vendor、build这些巨型目录grep 会一股脑全扫进去又慢又杂。正确的姿势是用--exclude-dir把无关目录排掉grep -rn --exclude-dirnode_modules --exclude-dir.git getUserInfo src/如果只想搜特定类型的文件用--include限制grep -rn --include*.java getUserInfo src/只看文件名、不要内容可以用-l只统计文件数量用-l | wc -l。在特别大的代码仓库里--include和--exclude-dir配合基本是标配不然很容易扫出一个文件叫*.min.js全是压缩代码结果挤满屏幕真正的命中反而被淹没。4.2 查日志时带上上下文-A、-B、-C很多时候光搜出一个“ERROR”根本不够你得知道这行错误前面发生了什么、后面跟了什么。grep 提供了三个参数-B 3显示匹配行的前 3 行Before-A 3显示匹配行的后 3 行After-C 3显示匹配行前后的各 3 行Context日常排查日志我基本只用-C一次把上下文都带上grep -n -C 5 NullPointerException app.log如果错误日志量很大还可以配合tail -f做实时过滤看线上新产生的报错tail -f app.log | grep --line-buffered -E ERROR|Exception--line-buffered很关键。不加它时grep 会先攒一段输出再打印你在终端上看到的错误会有明显延迟加上它之后grep 每匹配一行就立刻输出实时性完全不一样。这也是我踩过坑才记住的细节一开始还以为 tail -f 失灵了。4.3 另一个准确率更高的搜索思路先 find 再 grep在大目录里搜内容直接grep -r是最省事的但未必是最快的。如果你知道要找的文件大概在哪里或者想按文件名字先圈定范围可以先用 find 找到具体文件再交给 grep。比如在 /opt 下所有.conf文件里搜端口配置find /opt -name *.conf -type f -exec grep -Hn listen {} \;find 和 grep 搭配的好处是可控性更强。你可以先看 find 找出了哪些文件确认范围没问题再批量 greek避免 grep -r 扫到一堆不想看的文件。也可以借助 xargs 把文件列表传给 grepfind /opt -name *.yml -type f | xargs grep -n password不过文件路径里如果带空格直接| xargs grep可能会出错更稳妥的是xargs -d \n grep -n。个人经验是路径里有空格的情况虽然不常见但一旦出现xargs报错很难一眼看出来提前写上-d \n能省很多事。这也算是被坑过的经验了。5. 常见问题、避坑经验与排查速查表5.1 我踩过的几个坑提前帮你避开第一个坑是自匹配前面已经讲过了解决方式就是[j]ava或pgrep。第二个坑是 grep 搜出来的二进制文件终端会提示Binary file xxx matches但不显示具体内容。如果日志里混入了二进制内容可以用grep -a强制把二进制当作文本处理我处理 Java 进程 dump 出来的堆转储时经常用。第三个坑是编码问题。有次我在日志里搜中文关键字明明在 vim 里能看到用 grep 就是搜不到。后来查了一下是文件编码是 GBK而终端和 grep 用的 locale 是 UTF-8。解决办法是先把文件转码再搜或者用iconv -f GBK -t UTF-8 file.log | grep 关键字。老系统上这问题出现频率不算低遇到怪事时先别怀疑 grep 坏了先看看文件编码。第四个坑是grep慢。大文件加复杂正则时确实会慢尤其正则写得不合适的时候。比如grep -E .*error.*这种开头的.*会让正则引擎做大量回溯性能很差。能缩小范围就缩小用^.*error不如直接error很多时候 grep 默认就是逐行包含匹配不需要额外写.*。真遇到超大文件还可以用LC_ALLC grep提升速度因为 C locale 下排序和匹配规则简化了。实测大文件上能快不少。5.2 常见问题速查表现象常见原因解决方式搜不到但 vim 里能看到文件编码与 locale 不一致先 iconv 转码或调整 LANG结果里总是多一个 grep 进程grep 自匹配用[j]ava或pgrep -f提示 Binary file matches匹配到了二进制文件加-a强制文本模式匹配行太多终端卡住没有限制输出量追加 大文件搜索慢正则回溯或 locale 影响简化正则加LC_ALLC$、*等符号搜不出来shell 先展开了变量或通配符用单引号包裹模式tail -f配 grep 有延迟管道缓冲加--line-buffered忘了排除目录搜出一堆 node_modules没有用--exclude-dir加排除项后重搜这里我再补一个细节。grep默认匹配的是包含关系也就是“这一行里包含某个模式就算命中”。如果你想精确匹配整行要加-x或者用^模式$来锚定。比如查进程时ps -ef | grep -x ...基本用不上但处理配置文件时如果只想找某个 key 单独占一行的情况-x就很有用了。5.3 grep 在整个命令体系里的位置顺便聊聊面试高频考点说了这么多最后把 grep 放到整个 Linux 命令体系里看一眼。以日志分析为例经典的组合是grep sed awkgrep 负责按模式捞行sed 负责批量替换和按行提取awk 负责按列做统计。这三者配合基本能解决 80% 的日常文本处理需求。比如统计某个接口的平均响应时间可以用grep GET /api/user access.log | awk {print $NF} | awk {sum$1;count} END {print sum/count}很多公司的运维和后端面试题都会围绕这个组合展开比如“统计日志中每个 IP 出现的次数”“找出耗时最长的请求”等等。核心考点就是考察你能不能把 grep 的筛选、awk 的分列、sort/uniq 的统计组合起来。建议平时多拿手头的日志练手练熟了面试时基本不用背题。最后分享一个小技巧给 grep 加上颜色和行号的习惯如果让我总结一个最值得长期坚持的习惯那就是让 grep 默认带颜色。虽然很多发行版默认就会alias grepgrep --colorauto但如果你发现自己的 grep 输出里没有高亮可以在~/.bashrc里加上alias grepgrep --colorauto颜色高亮的好处不是好看而是在一大屏输出里命中位置一眼就能扫出来。尤其配合-n显示行号排查效率能提升一个档次。到现在为止grep 的基础用法、正则进阶、进程组合、日志排查、避坑经验都过了一遍。你如果只记住一件事那就记住先过滤再处理。grep 永远是管道的第一道关卡也是你面对一堆未知信息时最应该先拿出来的工具。下次再遇到“查进程、查日志、查配置”的需求希望你能直接想到该用哪条命令。

相关新闻

2026/9/7 15:25:04

Rust NLL 详解:从词法作用域到程序点的借用检查进化

你大概率遇到过这种场面:代码逻辑清清楚楚,上一行刚读完某个引用,下一行想对原变量做一次修改,编译器却甩出一句cannot borrow as mutable because it is also borrowed as immutable,把整个作用域都冻结了。我第一次遇…

2026/9/7 15:20:02

多模型架构实战:GLM 与 Gemini CLI 的融合接入指南

做 AI 编码工具最头疼的一件事,就是赌模型。HagiCode 从最初只支持单一后端开始,被用户反复追问“能不能接入 GLM”“能不能走 Gemini CLI”之后,我终于意识到多模型不是加分项,而是生存项。这次改动把 GLM 全系模型正式接入&…

2026/9/7 15:20:02

Python数据分析三剑客:NumPy、Pandas与Matplotlib实战指南

先给各位刚入坑 Python 数据科学的朋友说句实在话:在真正动手处理一批乱糟糟的数据之前,你很难体会到 NumPy、Pandas、Matplotlib 这三个库到底能省多少事。我见过太多人一上来就啃官方文档,结果被axis0和axis1绕晕,被中文字体乱码…

2026/9/7 19:15:37

IOPaint 低内存模式实战:4GB 显存也能跑 Stable Diffusion

IOPaint 低内存模式实战:4GB 显存也能跑 Stable Diffusion 【免费下载链接】IOPaint Image inpainting tool powered by SOTA AI Model. Remove any unwanted object, defect, people from your pictures or erase and replace(powered by stable diffusion) any th…

2026/9/7 19:15:37

信创环境下百度UE编辑器识别WORD粘贴格式的实用适配方案

我没有直接操作过信创目录里那几款政务系统的UE集成,但基于在信创环境下做政务系统前端改造的踩坑经验,这个问题我可以负责任地告诉你:百度UE(UEditor/UMEditor)默认情况下,几乎无法完美识别直接从WORD粘贴…

2026/9/7 19:15:37

纯CSS卡片式布局:从盒模型到阴影间距的实战指南

卡片式布局现在是前端日常开发里绕不开的基本功,不管是后台管理系统的数据看板,还是移动端的信息流页面,甚至个人博客的文章列表,拆开来看都是一张张卡片。很多初学者能写出“看着像卡片”的界面——有背景色、有圆角、有阴影&…

2026/9/7 0:47:43

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/7 0:14:19

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/7 0:14:17

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/7 0:03:36

基于YOLOv8和PyQt5的麦穗稻穗检测识别系统设计与实现

这次我们来看一个把目标检测算法和桌面端工具结合得很典型的项目:基于 YOLOv8 PyQt5 的麦穗稻穗检测识别系统。这个项目本身不是新概念,但它的价值在于落地形态很完整。YOLOv8 负责核心的麦穗稻穗目标检测,PyQt5 负责提供可视化的桌面交互界…

2026/9/7 0:03:36

UL 1642锂电池安全标准全解析:测试项目、认证流程与避坑指南

简介:UL 1642是锂电池安全领域的重要规范,本中文版资源适合锂电池制造商、检测机构工程师及产品认证相关人员阅读,用于理解电池在设计与制造层面的安全要求、测试方法与合规要点。资源共1个PDF文件,压缩包大小834KB,便…

2026/9/7 0:03:36

BS EN 13814-1-2019游乐设施安全标准:设计与制造核心要点解析

简介:BS EN 13814-1:2019是英国采纳欧洲标准EN 13814-1:2019的正式版本,由BSI标准出版,重点规定游乐设施和游乐设备在设计与制造环节的安全准则,与BS EN 13814-2:2019、BS EN 13814-3:2019共同取代旧版BS EN 13814:2004。该标准面…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/6 19:33:50

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/6 10:19:40

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…