Linux 三剑客之 grep 文本搜索利器
grep、sed、awk 号称 Linux 三剑客,处理文本各有分工。这篇先说清三者大致的活儿,再重点拆 grep:基础查找、正则匹配、常用参数,以及配合管道的实战套路。搞定 grep,日志排查和文本过滤就顺手多了。
在 Linux 上跟文本打交道,绕不开三个命令:grep、sed、awk。
江湖上给它们起了个响亮的名号,叫“三剑客”。
我刚接触的时候也懵,明明都是处理文本,为啥要三个?后来用多了才明白,它们分工不一样,各管一摊。
这篇先把三剑客的活儿捋清楚,然后重点把 grep 拆开讲透。
三剑客各自干啥
先给个大概印象,别急着记细节。
- grep:负责找。从一堆文本里把符合条件的行捞出来,它只管筛选,不改内容。
- sed:负责改。流式编辑器,擅长按行做替换、删除、插入,改文本内容的活儿交给它。
- awk:负责算。它把每行按列切开,能取字段、能统计、能做运算,处理结构化文本最拿手。
打个比方,一份日志摆在面前:
- 想挑出所有报错的行 → grep
- 想把里面的旧域名批量换成新域名 → sed
- 想统计每个接口被调用了多少次 → awk
三个各有各的战场。今天我们只聊 grep,另外两位以后再单独开篇。
grep 是干嘛的
grep 的名字来头挺有意思,是 “global regular expression print” 的缩写。
翻译过来就是:全局正则匹配并打印。
说人话,就是在文件里逐行搜索,把匹配上的行打印出来。
最基础的用法就一个套路:
# grep 要找的内容 文件名
grep "error" app.log
这行命令会把 app.log 里所有包含 error 的行都打出来。
就这么简单,一个词就能开干。
它也能配合管道,接收前面命令的输出:
# 从进程列表里揪出 nginx 相关的进程
ps -ef | grep nginx
这个组合我几乎天天用,找进程、查端口、翻日志,管道接 grep 是肌肉记忆了。
几个天天用的参数
grep 参数不少,但真正高频的就那么几个。挑我自己按得最多的说。
-i 忽略大小写
日志里 Error、ERROR、error 混着写,一个个找太累。加 -i 全都不区分:
# 大小写通吃
grep -i "error" app.log
-n 显示行号
找到了还想知道在第几行,加 -n:
grep -n "timeout" app.log
输出前面会带上行号,方便你直接跳到文件那一行去看。
-v 反向过滤
有时候我不是想找什么,而是想排除什么。-v 把不匹配的行留下:
# 看日志,但不想看那些 DEBUG 的噪音
cat app.log | grep -v "DEBUG"
这个特别实用,日志里 DEBUG 刷屏的时候,一个 -v 世界就清净了。
-c 只数个数
不想看内容,只想知道有多少行匹配,用 -c:
# 今天报了多少次 error
grep -c "error" app.log
直接返回一个数字,比 grep ... | wc -l 省事。
-r 递归搜目录
不知道内容在哪个文件里,想在整个目录里翻,用 -r:
# 在 src 目录里递归找 mebugs 这个词出现在哪些文件
grep -r "mebugs" ./src
它会把匹配到的文件路径和行内容一起列出来。找代码里某个变量在哪定义、哪引用,靠它。
上下文一起看
光看匹配那一行,有时候信息不够。报错行的上下几行往往才是关键。
grep 有三个参数专门干这个:
-A n:显示匹配行后面(After)n 行-B n:显示匹配行前面(Before)n 行-C n:前后(Context)各显示 n 行
# 找到 error 那行,连带后面 5 行一起看,通常异常堆栈就在后面
grep -A 5 "error" app.log
# 前后各看 3 行,掌握上下文
grep -C 3 "NullPointerException" app.log
排查异常堆栈的时候,-A 简直救命。光一行 error 你啥也看不出来,把后面的栈跟出来才知道是哪炸了。
正则才是 grep 的灵魂
前面都是找固定的词。grep 名字里那个 “regular expression”(正则)才是它的真本事。
匹配的不再是死字符串,而是一种模式。
基础正则
默认的 grep 用的是基础正则,几个常用符号:
^:匹配行首$:匹配行尾.:匹配任意一个字符*:前一个字符出现 0 次或多次
# 找出所有以 2026 开头的行(比如日志时间戳)
grep "^2026" app.log
# 找出所有以分号结尾的行
grep ";$" app.log
# 找出空行
grep "^$" app.log
那个找空行的 ^$ 我一开始还觉得挺妙,行首紧接着行尾,中间啥都没有,可不就是空行嘛。
扩展正则用 -E
基础正则里 +、?、| 这些得加反斜杠转义,写着别扭。加个 -E 切到扩展正则,就能直接用:
# 匹配 error 或 warn,任意一个都行
grep -E "error|warn" app.log
# 匹配 laowang 或 laozhang(la 后面接 owang 或 ozhang)
grep -E "la(owang|ozhang)" users.txt
| 是“或”的意思,一次匹配多个关键词,比连着敲两次 grep 舒服。
个人习惯是要用到 | 或者 + 就直接上 -E,省得数反斜杠。
精确匹配整个单词
找 name 的时候,username、filename 这些也会被带出来,很烦。-w 只匹配完整单词:
# 只匹配独立的 name,不匹配 username
grep -w "name" config.txt
串起来的实战套路
单个命令说完了,真正好用的是组合。举几个我常用的。
管道层层过滤
grep 可以一个接一个,逐层收窄:
# 先揪出 error,再从里面排掉超时的,剩下的才是我真正关心的
cat app.log | grep "error" | grep -v "timeout"
一层一层筛,思路很直观,条件复杂时比写一个大正则清楚多了。
配合 tail 实时盯日志
线上出问题,我喜欢一边刷请求一边盯日志:
# 实时跟踪日志,只看带 error 的新行
tail -f app.log | grep "error"
tail -f 持续输出新日志,grep 帮你只留报错,噪音全滤掉,眼睛不累。
统计接口调用
想知道某个接口今天被打了多少次:
# 数一下 /api/login 出现多少次
grep -c "/api/login" access.log
配合前面的参数,排查问题的效率能上一个台阶。
小结
绕了一圈,把 grep 从头到尾过了一遍。
三剑客的分工先记住:grep 找、sed 改、awk 算。今天主角是 grep。
grep 本身的要点也就几条:
- 基础用法就是
grep 内容 文件,配合管道接前面命令的输出 - 高频参数:
-i忽略大小写、-n带行号、-v反向排除、-c数个数、-r递归搜目录 - 排查异常用
-A/-B/-C把上下文一起拉出来 - 想玩出花,
-E上扩展正则,|一次匹配多个关键词
grep 是三剑客里最好上手的一个,学会它日志排查立马轻松一大截。
sed 和 awk 那两位更硬核,等有空了我们再单独聊。
那就先拿 grep 开练吧。
