许多用户误以为 grep 不支持正则表达式,实际上这是一个普遍的认识误区。事实上,grep 默认使用基础正则表达式(BRE),原生支持 ^、$、.、* 等常见元字符。若需使用扩展正则(ERE)或 Perl 兼容正则(PCRE),只需分别添加 -E 和 -P 参数即可。因此,认为“grep 不支持正则表达式”的说法显然站不住脚。

grep 默认采用基础正则(BRE),并非你习惯的 Perl 风格
很多人一上手就写 grep "d+",结果直接报错。原因很简单:d 是 PCRE(Perl)中的语法,grep 默认并不识别。它默认使用的是基础正则表达式(BRE),像 +、?、| 这类元字符,必须加上反斜杠才能生效——例如 + 才表示“一个或多个前一项”。
- 若想使用
+、?、|、( )等符号,需要添加-E参数:正确写法是grep -E "a+|b",而非grep "a+|b" -P参数允许直接调用d、w、lookbehind等 PCRE 特性,但并非所有系统都支持(例如 Alpine Linux 的 busybox grep 就缺少-P选项)- 进行纯文本搜索时不必硬套正则——使用
grep -F或fgrep更快速且更安全,尤其当模式中包含.、*、[等 shell 敏感字符时
匹配单词边界请用 -w,不要依赖 b
b 在 BRE 中并非单词边界(那是 PCRE 才有的概念),grep 默认根本不识别 b。如果强行使用 grep "berrorb",grep 只会字面匹配字母 b 和 e,结果完全偏离预期。
- 要精确匹配完整单词
error(同时排除errors或enderror),使用grep -w "error"即可 - 如果非要用正则控制边界,BRE 中可以用
和:例如>grep "(注意此处使用反斜杠加小于/大于号,而非" b) -w选项比手写<...>更可靠,兼容性也更佳;-x则用于整行精确匹配,比如grep -x "OK"仅匹配单独一行恰好为“OK”的情况
递归搜索配合正则时,-r 和 --include 需要搭配使用
仅写一句 grep -r "pattern" /var/log,它会扫描所有文件——包括二进制文件、压缩包、socket 文件。轻则报“Binary file xxx matches”,重则导致进程卡住甚至遗漏关键结果。
- 限定文件类型:添加
--include="*.log"或--include="*.conf",例如grep -r -E "timeout|fail" /etc --include="*.conf" - 排除不需要的目录:使用
--exclude-dir="cache"或--exclude-dir=".git",避免无谓的遍历 - 遇到“Permission denied”提示时,不必急于加
2>/dev/null掩盖——先确认是否真的需要读取那些路径;必要时使用sudo grep -r ...,但需明确权限影响的范围
管道传入正则时,别忘了加引号和转义
从 ps 或 cat 通过管道将内容传给 grep,最容易出问题的是 shell 提前解析了正则中的特殊字符。
- 如果模式中包含空格、
$、*、(等,必须用单引号包裹:ps aux | grep 'nginx: worker',不能只用双引号甚至不加引号 - BRE 中的
^、$锚定依然有效,但^start在管道中匹配的是行首,而非整个输入的起始位置——这一细节常被忽略 - 想在管道里用
-E实现“或”匹配,例如ps aux | grep -E "(nginx|apache)",括号是必须的,否则grep会将它们视为普通字符处理,完全无法达到“或”的效果
正则表达式这块,最容易出错的地方在于“以为写了就生效”。实际效果取决于 grep 使用的引擎、引号是否包裹严密、上下文是否允许锚定——这些细节看似不起眼,但一旦出错,什么都查不出来。
