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 开练吧。

更多推荐

章节目录