Linux grep命令用法详解:文本搜索与过滤的15个实战场景(2026)

📝 821 字 · ☕ 3 分钟阅读

如果你在 Linux 下干活超过一天,那你一定用过 grep。它是那种「你以为自己会了,但其实只用了 20% 功能」的命令。

我自己最早用 grep 就是 grep 'error' log.txt,用了好几年。后来才发现——原来 grep 能干的事比我想象的多得多:正则匹配、递归目录、上下文显示、反向过滤、甚至配合管道做数据管道流。写这篇文章,就是想把我踩过的坑、学到的技巧、生产环境里真正好用的写法,一次性整理出来。

这篇文章假设你用的是 Ubuntu 24.04(其他发行版 grep 也是一样的,GNU grep 3.x)。废话不多说,直接开始。

一、grep 是什么

grep 全称 Global Regular Expression Print——全局正则表达式打印。说白了就是从文件或标准输入里,把匹配某个模式的行捞出来。

三个核心概念:

  • Pattern(模式):你要搜什么,可以是普通字符串,也可以是正则表达式
  • Input(输入):你要从哪里搜——文件、管道输入、标准输入
  • Output(输出):匹配到的行,默认输出到标准输出

先确认你系统上的版本:

$ grep --version
grep (GNU grep) 3.11
Copyright (C) 2023 Free Software Foundation, Inc.

GNU grep 3.x 是目前主流。和 BSD grep(macOS 自带)有些细微差别,后文会标注。

二、基本语法

grep [选项] '模式' [文件...]

最简单的用法——在单个文件里搜关键字:

$ grep 'error' /var/log/syslog
Jun  3 08:15:23 ubuntu-server kernel: [12345.678] error: usb 3-1: device descriptor read/64, error -71
Jun  3 08:16:01 ubuntu-server nginx[1234]: 2026/06/03 08:16:01 [error] 1234#1234: *1 connect() failed

也可以从管道接收数据——这是 grep 最常用的场景之一:

$ ps aux | grep nginx
www-data  1234  0.0  0.1  55232  8192 ?  S  08:00  0:00 nginx: worker process
root      1233  0.0  0.2  55808 16384 ?  Ss 08:00  0:00 nginx: master process

注意上面这个例子有个经典坑:ps aux | grep nginx 的结果里会包含 grep 进程本身。解决办法有两个:

# 方法1:用方括号让 grep 进程不匹配自己
$ ps aux | grep '[n]ginx'

# 方法2:用 grep -v 排除 grep 自身
$ ps aux | grep nginx | grep -v grep

第二种更通用,推荐记住。

三、核心选项:10 个你一定用得上的

3.1 -i:忽略大小写

搜 Error、ERROR、error 一次搞定:

$ grep -i 'error' /var/log/syslog

生产环境里搜日志,这基本是标配。

3.2 -v:反向匹配

排除包含某个关键词的行。比如看 syslog 里不是 info 级别的所有日志:

$ grep -v 'INFO' /var/log/app.log

结合管道排除注释行和空行,用来读配置文件特别实用:

$ grep -v '^#' /etc/nginx/nginx.conf | grep -v '^$'
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
    worker_connections 768;
}
http {
    sendfile on;
    ...

3.3 -r 或 -R:递归搜索目录

在项目目录里搜某个函数定义、某个配置项,这个太常用了:

$ grep -r 'worker_processes' /etc/nginx/
/etc/nginx/nginx.conf:worker_processes auto;
/etc/nginx/sites-available/default:#   worker_processes 4;

-r-R 的区别:-R 会跟随符号链接,-r 不会。日常用 -r 就够了。

3.4 -n:显示行号

配合编辑器快速定位:

$ grep -n 'server_name' /etc/nginx/sites-available/default
28:    server_name devlearn.club www.devlearn.club;
56:    # server_name example.com;

3.5 -c:统计匹配行数

想知道日志里有多少条 error,不关心具体内容:

$ grep -c 'ERROR' /var/log/app.log
247

3.6 -l:只列出文件名

在多个文件中搜,只想知道哪些文件包含这个关键词:

$ grep -rl 'TODO' ~/projects/
/home/user/projects/app/main.py
/home/user/projects/app/utils.py
/home/user/projects/app/config.py

3.7 -w:精确匹配整个单词

搜 “port” 但不匹配 “report” 或 “transport”:

$ grep -w 'port' /etc/ssh/sshd_config
Port 22
#GatewayPorts no

3.8 -o:只输出匹配的部分

不是输出整行,而是只输出匹配到的子串。配合管道提取数据非常强大:

$ echo 'IP: 192.168.1.100 connected' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
192.168.1.100

3.9 -A / -B / -C:显示上下文

这是排查问题时最有用的选项。看错误的前后几行,理解上下文:

# -A 2:匹配行及之后 2 行
$ grep -A 2 'FATAL' /var/log/app.log

# -B 3:匹配行及之前 3 行
$ grep -B 3 'FATAL' /var/log/app.log

# -C 2:匹配行及前后各 2 行(最常用)
$ grep -C 2 'FATAL' /var/log/app.log
2026-06-03 08:15:20 INFO  Processing request /api/users
2026-06-03 08:15:21 WARN  Database connection pool at 95%
2026-06-03 08:15:22 FATAL Out of memory: cannot allocate 1048576 bytes
2026-06-03 08:15:22 INFO  Shutting down gracefully
2026-06-03 08:15:23 INFO  Process exited with code 1

生产环境查问题,grep -C 5 'ERROR' 基本是我的肌肉记忆。

3.10 –color=auto:高亮匹配

Ubuntu 默认 alias 已经设了,但自己确认一下:

$ alias grep='grep --color=auto'

四、正则表达式:grep 的真正威力

grep 支持三种正则模式,通过选项切换:

选项 模式 说明
-G 基本正则(默认) ?, +, {, |, (, ) 需要转义
-E 扩展正则(推荐) 等价于 egrep,不需要转义
-P Perl 兼容正则 支持 lookahead/lookbehind 等高级特性

建议:日常直接用 grep -E 扩展正则可读性好,不用写一堆反斜杠。

4.1 常用正则模式速查

# 匹配多个关键词(或逻辑)
$ grep -E 'error|fail|fatal' /var/log/syslog

# 以某字符串开头
$ grep -E '^2026-06-03' /var/log/app.log

# 以某字符串结尾
$ grep -E '\.conf$' /etc/nginx/nginx.conf

# 匹配数字
$ grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' access.log

# 匹配邮箱
$ grep -E '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' users.txt

# 匹配 HTTP 状态码
$ grep -E ' (404|500|502|503) ' /var/log/nginx/access.log

五、实战:15 个生产环境常用场景

下面这些是我在服务器上反复用到的组合,直接复制就能用:

场景 1-5:日志分析

# 1. 查看最近 100 条错误日志
$ tail -100 /var/log/app.log | grep -i 'error'

# 2. 统计每个小时段错误数量
$ grep 'ERROR' /var/log/app.log | cut -d' ' -f2 | cut -d: -f1 | sort | uniq -c
   12 08
   34 09
   58 10

# 3. 找出所有 5xx 错误并统计 URL
$ grep -E ' (50[0-9]) ' /var/log/nginx/access.log | grep -oE '"[A-Z]+ [^ ]+' | sort | uniq -c | sort -rn
   42 "GET /api/users
   18 "POST /api/upload
    7 "GET /api/products

# 4. 实时监控错误(tail -f 配合 grep)
$ tail -f /var/log/app.log | grep --line-buffered -E 'ERROR|FATAL'

# 5. 查看某时间段内的日志
$ grep -E '2026-06-03 (08|09|10):' /var/log/app.log

场景 6-10:配置与系统管理

# 6. 查看所有生效的配置项(排除注释和空行)
$ grep -Ev '^#|^$' /etc/ssh/sshd_config
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

# 7. 查看哪些端口被监听
$ ss -tlnp | grep LISTEN
LISTEN  0  128  0.0.0.0:22    0.0.0.0:*  users:(("sshd",pid=890,fd=3))
LISTEN  0  511  0.0.0.0:80    0.0.0.0:*  users:(("nginx",pid=1234,fd=6))
LISTEN  0  511  0.0.0.0:443   0.0.0.0:*  users:(("nginx",pid=1234,fd=7))

# 8. 查找大文件(>100M)
$ find / -type f -size +100M 2>/dev/null | grep -v '^/proc/'

# 9. 查看系统上有哪些用户
$ grep -E '(/bin/bash|/bin/zsh)$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
ubuntu:x:1000:1000::/home/ubuntu:/bin/bash

# 10. 检查 crontab 有没有语法错误(排除注释)
$ crontab -l | grep -v '^#' | grep -v '^$'

场景 11-15:代码与数据操作

# 11. 在项目里搜索所有 TODO/FIXME
$ grep -rn 'TODO\|FIXME' ~/projects/ --include='*.py'

# 12. 找出 Python 文件里所有 import 语句
$ grep -rn '^import\|^from' ~/projects/ --include='*.py' | grep -v 'venv'

# 13. 提取 JSON 或日志中的特定字段
$ grep -oP '"email"\s*:\s*"\K[^"]+' users.json
alice@example.com
bob@example.com

# 14. 统计代码行数(排除空行和注释)
$ grep -rv '^\s*$\|^\s*#' ~/projects/app.py | wc -l
2847

# 15. 检查 nginx 配置语法
$ nginx -t 2>&1 | grep -E 'successful|failed'
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

六、性能优化提示

grep 本身已经非常快(GNU grep 用了 Boyer-Moore 算法),但有几个习惯可以让它更快:

  • 指定文件类型grep -rn 'pattern' --include='*.py' 比遍历所有文件快得多
  • 用 LC_ALL=CLC_ALL=C grep 'pattern' largefile.txt 在处理纯 ASCII 文本时能快 2-10 倍,因为它跳过 Unicode 排序规则。我处理 GB 级日志时一定加这个
  • 用 fgrep / grep -F:如果搜的是固定字符串(不是正则),用 grep -F 可以跳过正则引擎,速度更快
  • 别递归太深grep -r 从根目录 / 开始跑是灾难。限制搜索深度或指定目录

实测对比(在 500MB 日志文件上):

$ time grep 'ERROR' large.log
real    0m0.847s

$ time LC_ALL=C grep 'ERROR' large.log  
real    0m0.152s

$ time grep -F 'ERROR' large.log
real    0m0.134s

搞大文件处理的时候这差距能救命。

七、常见问题 FAQ

Q: grep 和 egrep、fgrep 有什么区别?

egrep 等价于 grep -E(扩展正则),fgrep 等价于 grep -F(固定字符串)。它们本质上是同一个程序,只是历史遗留的别名。现代 Linux 上可以直接用 grep -Egrep -F,不需要记 egrep/fgrep。

Q: grep 返回 “Binary file matches”,怎么让它显示内容?

grep 检测到文件是二进制时会跳过内容只告诉你「匹配到了」。加上 -a(或 --text)选项强制把文件当作文本处理:grep -a 'pattern' binaryfile。这在某些「看起来像文本但被标记为二进制」的文件(比如带 BOM 的 UTF-16 文件)上特别有用。

Q: macOS 上的 grep 怎么和 Linux 不一样?

macOS 自带的是 BSD grep,和 GNU grep 有细微差别。比如 BSD grep 不支持 -P(Perl 正则),-r 行为也略有不同。解决方案:brew install grep,然后使用 ggrep 命令,它就是 GNU grep。或者直接用 Docker 里的 Linux 环境跑。

Q: 怎么在 grep 结果中用不同颜色突出显示?

设置 GREP_COLORS 环境变量。默认匹配部分用红色加粗。自定义示例:export GREP_COLORS='ms=01;32:mc=01;33:sl=:cx=:fn=35:ln=32:bn=32:se=36'ms 控制匹配文字样式,mc 控制匹配文字的颜色。01;32 表示加粗绿色。详细文档:man grep 搜索 GREP_COLORS。

总结

grep 看起来简单,但把 -E, -v, -r, -n, -C, -o 这几个选项玩熟,配合正则和管道,你就能在 Linux 上像庖丁解牛一样处理文本。

记住几个肌肉记忆的组合:

  • 查日志grep -C 5 'ERROR' /var/log/app.log
  • 读配置grep -Ev '^#|^$' /etc/nginx/nginx.conf
  • 搜代码grep -rn 'function_name' --include='*.py'
  • 大文件LC_ALL=C grep -F 'needle' huge.log

如果你觉得 find 命令也该武装一下,看看前几天的这篇:Linux find命令用法详解。find + grep 配合起来,基本能解决服务器上 90% 的查找问题。

有问题评论区见,我去接着修 bug 了 🐛

📤 分享这篇文章