做什么

在文件或输入流里按正则匹配查找行。命令行核心工具之一。

常用参数

参数 含义
-i 忽略大小写
-n 显示行号
-v 反向(不匹配的行)
-r / -R 递归找目录
-l 只显示文件名
-c 只数匹配行数
-A N 匹配行 + 后 N 行
-B N 匹配行 + 前 N 行
-C N 匹配行 + 前后各 N 行
-E 扩展正则(启用 `
-F 字面匹配(不当正则)
-o 只输出匹配的部分
-w 整词匹配
--color=auto 高亮匹配
--include="*.py" 递归时只看某后缀
--exclude-dir=node_modules 递归时排除目录

实战

grep ERROR app.log
grep -i error app.log                 # 忽略大小写
grep -n ERROR app.log                 # 加行号
grep -v DEBUG app.log                 # 排除 DEBUG 行
grep -c ERROR app.log                 # 数有多少行

# 递归搜代码
grep -rn "TODO" src/
grep -rn --include="*.py" "import os" .

# 多模式
grep -E "(error|warning)" app.log
grep "error\|warning" app.log

# 整词
grep -w "log" file.txt               # 不匹配 "logger" 等

# 上下文
grep -A 3 ERROR app.log              # 后 3 行
grep -B 2 ERROR app.log              # 前 2 行
grep -C 2 ERROR app.log              # 前后各 2 行

正则速查

.       任意一个字符
*       前面字符 0+ 次
+       前面字符 1+ 次(需 -E 或 \+)
?       前面字符 0/1 次(需 -E 或 \?)
^       行首
$       行尾
[abc]   字符集中之一
[^abc]  字符集外的
[0-9]   数字
\d      数字(需 -P)
\b      词边界
|       或(需 -E 或 \|)

实战 2:分析 Nginx 日志

# 找 5xx
grep " 5[0-9][0-9] " access.log

# IP 频次
grep -oE '^[0-9.]+' access.log | sort | uniq -c | sort -rn | head

# 看 ERROR 上下文
grep -C 5 "Connection refused" app.log

现代替代:ripgrep(rg)

sudo apt install ripgrep
rg "TODO" src/

rg 是 Rust 写的——比 grep 快 5-10 倍,默认递归 + 默认尊重 .gitignore。日常代码搜索强烈推荐。

  • 默认 grep 是 POSIX 基本正则——+ ? | 需要 \+ \? \| 或用 -E
  • grep -r 在某些 GNU 版本默认不跟软链接——加 -r vs -R(不同 GNU 版本略有差异)
  • 大文件 grep 慢——加 LC_ALL=C grep(关掉 unicode 处理)能快几倍