1. 为什么grep是Linux运维的第一道防线
很多人第一次接触Linux,都是从找东西开始的。日志报错要找关键字,配置文件要确认某项开关是否生效,进程列表里要捞特定程序,一串命令输出要筛选有价值的信息。而grep,就是这套场景下最顺手、最常用的那个工具。它说不上多复杂,但用好了,日常排查效率能提升一个层级。
先说一下grep这个名字的来历。它的全称是global regular expression print,意思是全局正则表达式打印。简单理解就是:你给它一串文本,它按照你指定的模式逐行匹配,把符合条件的行输出到屏幕上。这个“模式”可以是普通字符串,也可以是正则表达式——这也是grep最强大的地方。
实际工作中,grep很少单独使用,绝大多数场景是和其他命令配合,通过管道把前一个命令的输出喂给它做过滤。比如:
bash复制dmesg | grep -i error
cat /etc/ssh/sshd_config | grep -v "^#"
ps aux | grep nginx
这样的管道组合,几乎是Linux运维每天都要敲几百遍的东西。与其说是命令,不如说它是一套组合拳里的核心连接件。
这篇文章我打算从实际操作出发,把grep的常用参数、正则写法、管道配合以及一些容易踩的坑全部过一遍。无论你是刚接触Linux的初学者,还是已经用了一段时间但总感觉差点意思的开发者,应该都能从这里找到有用的内容。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心参数解读:先掌握这批就够日常使用了
grep的参数非常多,但真正高频使用的基本就是十几个。我按使用频率从高到低整理了一下。
2.1 高频参数速查表
| 参数 | 全称 | 作用 |
|---|---|---|
| -i | --ignore-case | 忽略大小写 |
| -v | --invert-match | 反向匹配,输出不符合条件的行 |
| -n | --line-number | 显示匹配行的行号 |
| -c | --count | 只统计匹配行数 |
| -r / -R | --recursive | 递归搜索目录下所有文件 |
| -l | --files-with-matches | 只列出包含匹配内容的文件名 |
| -L | --files-without-match | 只列出不包含匹配内容的文件名 |
| -E | --extended-regexp | 使用扩展正则表达式 |
| -o | --only-matching | 只输出匹配到的部分,而非整行 |
| -A num | --after-context | 输出匹配行及之后num行 |
| -B num | --before-context | 输出匹配行及之前num行 |
| -C num | --context | 输出匹配行及前后各num行 |
这里我想特别提一下 -E。很多人第一次用grep写正则的时候,会遇到“明明我的正则没问题,怎么就是不生效”的情况。多半是因为默认情况下grep使用的是基础正则表达式,在一些符号的处理上和扩展正则不一样。最典型的区别就是量词符号,基础正则里需要加反斜杠才能表示“一次或多次”这类含义,而加上了 -E 参数之后,写起来就自然多了,和大多数语言里的正则写法一致。
举个例子,想匹配一个或多个数字:
bash复制# 基础正则写法
grep "[0-9]\+" file.txt
# 扩展正则写法
grep -E "[0-9]+" file.txt
两种都能用,但显然第二种更直观、更好记。所以我在实际使用中,凡是涉及正则的场景,都会直接加上 -E。
2.2 场景化用法说明
搜索日志时最常用的是 -i 和 -n 的组合。我排查NGINX错误日志时,经常记不清具体的错误级别是Error还是error,直接 grep -in "error" access.log 一把梭,大小写问题完全不用考虑。-n 能直接告诉你匹配在第几行,后面用sed或者vim跳转过去非常方便。
搜索整个目录时,-r 是标配。但注意,直接 grep -r "keyword" /etc/ 会把二进制文件也扫一遍,输出乱码体验很差。一般我会加一个 --exclude 参数把常见二进制格式排除掉,或者用 -I 参数让grep直接忽略二进制文件。个人习惯是直接 -rI 两个参数一起上,省心很多。
-A/-B/-C 这三个参数在做日志分析的时候特别有用。比如某个请求报错了,我只搜“ERROR”只能看到那一行,但问题往往出在报错前后几行的上下文里。我会用 grep -C 5 "ERROR" app.log,一次把报错前后5行都拉出来,基本等于给错误信息加了个上下文窗口,排查效率直接翻倍。
