grep默认匹配整行且区分大小写,不递归不高亮;常用选项包括-i(忽略大小写)、-n(显示行号)、--color=always(高亮)、-r(递归搜索)、-a(强制文本处理)、--exclude-dir(排除目录);正则需注意BRE/ERE差异,-E启用扩展正则。

grep 基础用法:匹配行而不是“找文件”
很多人输完 grep keyword file.txt 发现没结果,第一反应是“没找到”,其实更可能是:文本里压根没有那行,或者大小写不一致。默认 grep 区分大小写、只输出匹配的整行,不递归、不高亮、不显示行号。
- 加
-i忽略大小写:grep -i "error" /var/log/syslog - 加
-n显示行号,方便定位:grep -n "timeout" app.log - 加
--color=always强制高亮(终端支持时),避免扫屏漏看:grep --color=always "failed" *.log - 注意通配符会被 shell 展开,
*.log是 bash 先处理再传给grep,不是grep自己识别通配符
递归搜索目录:用 grep -r,别硬套 find | xargs grep
grep -r 本质就是封装好的递归,比手动拼 find 更稳——尤其路径含空格或特殊字符时,xargs 默认按空白分割,容易崩。
- 基本递归:
grep -r "API_KEY" ./src/(会进子目录,但跳过二进制文件) - 想搜二进制(比如编译后的二进制里埋的字符串):加
-a强制当文本处理:grep -ra "debug_mode" ./build/ - 排除某些目录(比如
node_modules):grep -r --exclude-dir=node_modules "fetch" ./ - 注意
-r不等价于-R:老版本 GNU grep 中-R会跟随符号链接,-r不跟;新版本已统一,但脚本里建议坚持用-r
正则表达式坑点:默认是基础正则(BRE),不是 Perl 风格
写 grep "a+b" 想匹配 “ab” 或 “aaab”,结果没反应?因为 + 在基础正则里不是元字符,得写成 grep "a\+b" 或直接切到扩展模式。
- 用
-E启用扩展正则(ERE):grep -E "a+b|c{2,}" file.txt(这时+、{2,}、|直接生效) - 用
-P启用 Perl 正则(需 GNU grep ≥ 2.20):grep -P "(?(支持后行断言) - 但
-P不是所有系统都带(比如 Alpine Linux 的 busybox grep 就没它),生产脚本慎用 - 转义规则混乱?统一用单引号包裹模式:
grep -E '^start.*end$' config.ini,避免 shell 提前吃掉$或*
性能与误报:二进制文件、换行符、空格路径全得防
在项目根目录跑 grep -r "TODO" . 卡住?大概率是碰到了大二进制文件(如 node_modules/.bin/xxx)或压缩包(dist/app.zip),grep 会逐字节扫,还可能因非法 UTF-8 报一堆 Binary file xxx matches 警告。
- 加
--binary-files=without-match让grep直接跳过二进制文件,不警告也不匹配 - 用
--include="*.py"限定后缀,比*.py通配更可靠(后者依赖 shell 展开,没匹配到就传空参) - 路径含空格?
grep -r "key" "$DIR"(变量用双引号包住),别写grep -r "key" $DIR - 想快速失败?加
-m 1找到第一个就停:grep -rm 1 "version =" pyproject.toml
真正麻烦的是混合编码文件(比如 GBK 的日志混着 UTF-8 的代码),grep 不做编码转换,匹配可能失效。这时候得先用 iconv 或换工具,不是 grep 能扛的。










