grep 是什么
grep 逐行扫描输入,把匹配给定模式的行输出来,是文本过滤的起点工具。三个默认行为必须先记牢:区分大小写、按基本正则(BRE)解释模式、以及没有匹配时返回退出码 1。最后这一条影响所有脚本——在开了 set -e 的脚本里,grep 找不到任何匹配会直接让脚本终止,很多「脚本莫名中断」都源自这里。
基本信息
| 适用平台 | Linux、macOS、BSD(GNU grep / BSD grep);-P(PCRE)在 macOS 自带版本上不可用 |
|---|---|
| 命令语法 | grep [选项] 模式 [文件...];不给文件则从标准输入读取 |
| 常用选项 | -i 忽略大小写、-v 反选、-n 显示行号、-c 只输出计数、-o 只输出匹配片段、-w 全词匹配、-E 扩展正则、-F 固定字符串、-r/-R 递归、-l 只列文件名、-q 静默、-A/-B/-C 输出上下文、-m 限制匹配数 |
| 退出码 | 0 表示有匹配、1 表示无匹配、2 表示出错(文件不存在、正则非法) |
| 权限要求 | 受文件读权限与目录执行权限限制,读取系统日志通常需要 sudo |
典型使用场景
- 日志过滤:从大日志里挑出错误行,配合 -n 定位行号再用 sed 取上下文
- 统计出现次数:-c 统计匹配行数,配合 sort 与 uniq 做频次分析
- 脚本条件判断:用 -q 静默检测某个配置项或关键字是否存在
- 递归搜索代码与配置:-r 配合 --include 限定文件类型,快速找定义位置
- 提取字段:-o 只输出匹配部分,把日志里的 IP、时间戳抽出来
- 排除噪声:-v 过滤掉注释行、空行或已知的无关日志
常用示例
常用示例
grep ERROR app.log
grep -in 'timeout' app.log # 忽略大小写 + 行号
grep -cv '^#' app.conf # 反选计数(统计有效配置行)
grep -o 'ip=[0-9.]*' app.log | head # 只输出匹配片段
grep -E 'ERROR|WARN' app.log # 扩展正则做或匹配
grep -rn --include='*.conf' 'listen' /etc | head
grep -A2 -B2 'panic' app.log # 输出前后各两行上下文
grep -m 1 'started' app.log # 命中第一条即停止
if grep -q '^max_conn' /etc/app/app.conf; then echo set; fi常用选项对照
| 选项 | 作用 | 注意 |
|---|---|---|
| -E | 使用扩展正则(ERE) | | 与 ? 直接用,不必转义 |
| -F | 按固定字符串匹配 | 不做正则解释,速度最快 |
| -w | 全词匹配 | 避免 http 命中 https |
| -r / -R | 递归搜索目录 | -r 不跟随命令行列出的符号链接,-R 跟随全部 |
| -l / -L | 只列出含匹配 / 不含匹配的文件名 | 批量筛查文件时很高效 |
| -m N | 命中 N 条即停止 | 大文件里做存在性判断时省时间 |
基本正则与扩展正则的区别只在元字符是否需要转义:点号、星号、字符类两者一致,而加号、问号、竖线、圆括号在基本正则里必须写成 \+ \? \| \( \) 才表示特殊含义。写复杂模式时用 -E 可读性更好,纯字符串匹配则用 -F 最快。
在大文件或代码库里反复搜索时,按内容类型选择工具更划算:仓库内搜索用 rg(自动跳过版本库与忽略文件、默认并行);只做固定字符串匹配时 grep -F 明显快于正则,因为它完全不做正则解析。常见的组合还有统计频次与取上下文:grep -o '模式' 文件 | sort | uniq -c | sort -rn | head 做频次排行,先用 grep -n 拿到行号再用 sed -n 取前后范围还原现场。压缩日志直接用 zgrep 或 zcat 管道搜索,不必先解压。
模式里包含 shell 元字符时必须整体加引号,否则会被 shell 先解释:grep 'a|b' 与 grep a|b 的含义完全不同,后者会变成管道。带变量的模式用双引号,但要清楚变量展开的结果。
按结果形态选选项
| 需求 | 选项 | 输出 |
|---|---|---|
| 只要条数 | -c | 每个文件一行计数 |
| 只要命中的文件 | -l | 文件名列表 |
| 只要没命中的文件 | -L | 文件名列表 |
| 要上下文 | -A / -B / -C | 命中行前后若干行 |
| 只要匹配片段 | -o | 匹配到的部分 |
| 只要退出码 | -q | 无输出 |
给输出加颜色便于肉眼扫(--color=auto)是交互环境的习惯,但重定向到文件时颜色转义会混进内容,后续脚本与 diff 都会受影响,自动化流程里应当关掉。管道另一端如果是另一个 grep 或解析程序,用 -q 或 -c 能省掉整段输出。