grep 命令速查表 - Linux 文本搜索常用命令大全

从日志里捞报错、在仓库里找一个标识符的全部引用、判断脚本条件是否成立,都可归结为「按模式搜索行」,而 grep 的参数组合能覆盖其中九成。吃透四个就够:-r 递归、-i 忽略大小写、-C n 带上下各 n 行上下文、-E 启用扩展正则;有了它们,「找到了却不知道上下文」这个最常见的问题自然消失。多模式一组给出三条扩展路径:-e 多次指定、-f 从文件读模式、--include 与 --exclude 控制文件范围。递归一组要留意性能:在 node_modules、.git、dist 上无差别递归会慢到不可用,--exclude-dir 是必需项而非优化项。分工写在场景组里:grep 是行级筛选,awk 才是列级处理器并能做聚合,rg 默认递归且尊重 .gitignore。脚本里判断匹配用 -q 只看返回码。

系统与运维·共 38 条命令·最后更新 2026-07-21
grep文本搜索linux

典型使用场景

面向日常做日志检索与代码搜索的开发者。grep 的三个高频陷阱值得先说:默认是 BRE,`+` `?` `|` 必须转义或用 `-E`;`-o` 提取片段时不能省,否则统计会按整行算;递归搜索大目录必须用 `--exclude-dir` 排除 node_modules 与 .git,否则一次搜索能卡住几分钟。本表按基础搜索、递归、正则、上下文、多文件与常用场景六组组织,可直接当排错清单用。

递归搜索 Recursive 7

grep -r "pattern" dir/
递归搜索目录
grep -R "pattern" dir/
递归搜索(跟随符号链接)
grep -rn "pattern" dir/
递归并显示行号
grep -rl "pattern" dir/
只输出匹配文件名
grep -r --include="*.log" "pattern" dir/
只搜索指定类型文件
grep -r --exclude="*.tmp" "pattern" dir/
排除指定类型文件
grep -r --exclude-dir="node_modules" "pattern" dir/
排除目录

正则表达式 Regular Expression 9

grep -E "pattern" file
扩展正则(等价于 egrep)
grep "^start" file
匹配行首
grep "end$" file
匹配行尾
grep "\<word\>" file
匹配单词边界
grep -w "word" file
匹配整个单词
grep "[0-9]" file
匹配数字
grep "[^0-9]" file
匹配非数字
grep "a\|b" file
匹配 a 或 b(BRE)
grep -E "a|b" file
匹配 a 或 b(ERE)

上下文 Context 4

grep -A 3 "pattern" file
匹配行后再显示 3 行
grep -B 2 "pattern" file
匹配行前显示 2 行
grep -C 3 "pattern" file
匹配行前后各显示 3 行
grep -A 3 -B 2 "pattern" file
前 2 行后 3 行

多模式与文件 Multiple Patterns & Files 6

grep -e "pattern1" -e "pattern2" file
匹配多个模式
grep -f patterns.txt file
从文件读取模式
grep "pattern" file1 file2
搜索多个文件
grep "pattern" *.log
搜索通配符匹配的文件
grep -H "pattern" file
显示文件名
grep -h "pattern" file1 file2
不显示文件名

常用场景 Common Patterns 5

grep "error\|warning" app.log
搜索 error 或 warning
grep -rn "TODO\|FIXME" src/
搜索代码中的 TODO
grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" access.log
提取 IP 地址
grep -c "^$" file
统计空行数
grep -v "^#" file | grep -v "^$"
排除注释和空行

参数矩阵

参数作用示例
-i / -v忽略大小写 / 反向排除grep -i "error" app.log
-c统计匹配行数(不输出内容)grep -c "^$" file
-n / -H显示行号 / 显示文件名grep -rn "TODO" src/
-o只输出匹配片段而非整行grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" access.log
-q静默模式,只返回状态码(脚本用)grep -q "ready" app.log
-r / -R递归 / 递归并跟随符号链接grep -r "pattern" dir/
--include / --exclude限定或排除文件类型grep -r --include="*.log" "err" dir/
--exclude-dir排除目录,搜大项目必备grep -r --exclude-dir="node_modules" "x" .
-E扩展正则(+ ? | 无需转义)grep -E "a|b" file
-w / \< \>匹配完整单词而非词内部grep -w "cat" file
-A / -B / -C显示后 n 行 / 前 n 行 / 前后各 n 行grep -C 3 "FATAL" app.log
-e / -f多个模式 / 从文件读模式grep -e "p1" -e "p2" file
-l / -h只输出文件名 / 不输出文件名grep -rl "pattern" dir/

易错点与避坑指南

现象模式里写了 + ? | 却匹配不到。

原因grep 默认使用基本正则(BRE),这三个符号在 BRE 下是字面量。

处置加 -E 启用扩展正则,或把这些符号转义成 \+ \? \|。

现象想统计某项出现多少次,结果比实际多很多。

原因没加 -o,uniq 统计的是整行而非匹配片段。

处置加 -o 只输出匹配部分:grep -oE "模式" file | sort | uniq -c | sort -rn。

现象搜 "cat" 结果把 concatenate 也匹配出来了。

原因模式没有单词边界约束。

处置加 -w(或 BRE 下用 \<cat\>)限定为完整单词。

现象递归搜项目目录卡住,几分钟不出结果。

原因扫进了 node_modules、.git 等海量小文件目录。

处置加 --exclude-dir="node_modules" --exclude-dir=".git" 限定范围。

现象搜文件名里的点号,结果匹配到了任意字符。

原因.` 是正则元字符,字面使用未转义。

处置写成 \. 转义,或用 grep -F 按字面匹配。

现象脚本里 grep 的判断结果总是「不匹配」。

原因把 grep 的输出当成返回值,实际它输出内容并以退出码表达结果。

处置用 grep -q 只看退出码:if grep -q "pattern" file; then … fi。

现象搜到日志里了,但一行里有多个匹配时只算一次。

原因grep -c 统计的是匹配行数而非匹配次数。

处置需要出现次数时用 grep -o 提取后 wc -l,或用 grep -o | wc -l。

排障路径

  1. 1先看实际匹配到了什么

    grep -o "pattern" file

    -o 只输出匹配片段;没输出就说明没命中,可逐段简化模式再试。

  2. 2带上下文定位报错位置

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

    -n 给行号、-C 3 前后各三行,通常这几行就说明了问题。

  3. 3按类型限定搜索范围

    grep -rn --include="*.ts" "TODO" src/

    限定文件类型比全量搜后再过滤快得多。

  4. 4脚本里判断内容是否存在

    grep -q "ready" app.log

    静默模式只返回状态码,适合写进健康检查。

  5. 5统计各项出现次数

    grep -oE "error|warning" app.log | sort | uniq -c | sort -rn

    -o 不能省;先排序让相同值相邻再计数。

命令示例

递归搜索并带上下文

grep -rn -C 2 "handleError" src/

-C 2 表示匹配行前后各显示 2 行,-n 给行号便于跳转。找不到时先确认大小写——grep 默认区分大小写。

输出

src/api/client.ts-42-  try {
src/api/client.ts-43-    const res = await fetch(url)
src/api/client.ts:44-    handleError(res)
--
src/api/retry.ts-18-      handleError(new Error("timeout"))

从日志里提取并统计 IP 地址

grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' access.log | sort | uniq -c | sort -rn | head

-o 只输出匹配到的部分而非整行,这样才能喂给 sort | uniq -c 统计。不加 -o 拿到的是整行,计数没有意义。

输出

   1842 203.0.113.7
    931 198.51.100.22
    407 192.0.2.180

只搜索特定类型文件并排除依赖目录

grep -rn --include="*.ts" --include="*.js" --exclude-dir=node_modules "API_KEY" .

--include 可重复指定;--exclude-dir 跳过 node_modules 之类的大目录,既快又避免结果被依赖代码淹没。

常见坑与注意事项

  • grep 默认区分大小写,搜不到时先试 -i。
  • 模式里的元字符(. * + ? [ ])会被当正则解释,搜字面量要加 -F 或转义;搜 a.b 会连 axb 一起命中。
  • 递归搜仓库不加 --exclude-dir=node_modules 会产生大量无结果且拖慢速度。
  • grep -r 不跟随符号链接,依赖目录若是指向别处的软链会搜不到,需要 -R。
  • 用 -o 提取子串时不要忘加,否则 uniq 统计的是整行而非匹配片段。

提示

  • grep 默认使用 BRE(基本正则),+、?、| 需转义或用 -E 启用 ERE。
  • 递归搜索大目录时加 --exclude-dir 排除 node_modules、.git 等。
  • grep -q 用于脚本中判断是否匹配,不输出内容只返回状态码。
  • grep -rn --include='*.ts' --exclude-dir=node_modules 只搜指定后缀的源码文件,比先 find 再传参少一层管道且天然跳过二进制。
  • grep -o 只输出匹配部分而非整行,配合 sort | uniq -c 可以统计某个字符串在日志里出现的次数分布。
  • grep -v -F -f 黑名单.txt 用固定字符串模式按文件排除一批模式,配置类文件批量清理时比写一长串正则更可靠。

常见问题

grep -r 和 grep -R 有什么区别?

小的 r 只递归普通目录和文件,遇到符号链接不跟随;大写的 R 额外会跟随符号链接一起搜。如果代码仓库里 node_modules 或 ~/.cache 之类是指向别处的软链,用 -r 会漏掉其中的内容,用 -R 才搜得到。另外在 GNU grep 里 -r 基本等价于 --recursive,但 macOS 的 BSD grep 两者行为一致。

怎么只搜索某种文件类型的内容?

加 --include:grep -rn --include="*.log" "error" . 只在 .log 文件里搜。多个模式用 --include="*.ts" --include="*.js" 连写即可。相对地,--exclude 可以排除掉 node_modules、dist 这类目录,避免结果里全是依赖代码。

grep 匹配不到明明存在的字符串是什么原因?

最常见是大小写没匹配,grep 默认区分大小写,需要 -i;其次是特殊字符被当成正则元字符,搜 a.b 会匹配到 axb 这类内容,要搜字面量就加 -F 或对元字符转义。再就是文件里有不可见字符或行尾 CRLF(Windows 换行)导致行尾匹配失败,可以直接搜回车符确认。

grep 输出的 -n、-c、-l、-o 各自适合什么场景?

-n 显示行号,方便定位和跳转,是最常加的;-c 只输出匹配行数不输出内容,适合做统计判断;-l 只列出含匹配的文件名,批量改文件前先看它圈定范围;-o 只输出匹配到的部分本身,配合 sort | uniq -c 能把日志里出现最多的关键词统计出来。

怎么一次匹配多个关键词?

两种方式:管道接起来最清晰,grep "error" app.log | grep "timeout" 依次过滤;或者用 -e 一次指定多个模式,grep -e "error" -e "timeout" app.log,效率更高只需扫一遍文件。模式较多时还可以用 -f patterns.txt 从文件读入。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们