跳转至

grep 与正则筛选

grep 按行搜索匹配内容。它适合回答“哪些行包含目标模式”,不负责复杂字段计算或修改原文件。

基本用法

grep 'ERROR' app.log
grep -i 'timeout' app.log
grep -n 'listen' nginx.conf
grep -v '^#' nginx.conf
grep -c 'failed' app.log
grep -l 'password' *.conf
grep -H 'ERROR' /var/log/app/*.log
选项 作用
-i 忽略大小写
-v 反向选择不匹配行
-n 显示行号
-c 输出匹配行数量
-l 只输出包含匹配的文件名
-o 只输出匹配片段
-q 静默,仅用退出码判断
-w 匹配完整单词
-x 整行完全匹配

上下文与递归

grep -A 3 -B 2 'Exception' app.log
grep -C 5 'OutOfMemoryError' app.log
grep -RIn --exclude='*.gz' --exclude-dir=.git 'server.port' .
  • -A 显示匹配后若干行。
  • -B 显示匹配前若干行。
  • -C 同时显示前后上下文。
  • -R 递归并跟随符号链接;多数场景更谨慎地使用 -r

在大型目录先限定路径、文件类型和时间范围,避免搜索 / 或数据目录造成高 I/O。

BRE、ERE 与固定字符串

grep 'error' file          # 基本正则 BRE
grep -E 'error|timeout' file
grep -F 'a.b[0]' file      # 固定字符串,不解释正则符号

历史命令对应关系:

egrep  = grep -E
fgrep  = grep -F

egrepfgrep 已被 POSIX 淘汰,GNU grep 也计划最终移除;新脚本使用 grep -Egrep -FGNU grep 说明

常用扩展正则

写法 含义
^ERROR 行首为 ERROR
timeout$ 行尾为 timeout
[0-9]+ 一个或多个数字(需 -E
WARN|ERROR WARN 或 ERROR(需 -E
[^[:space:]]+ 一个或多个非空白字符
\bfailed\b 单词边界,具体可移植性需确认
grep -E 'HTTP/[0-9.]+" (500|502|503|504) ' access.log
grep -E '([0-9]{1,3}\.){3}[0-9]{1,3}' app.log

正则中的 . 表示任意字符,要匹配点号写 \.。IPv4 示例只匹配形状,不验证每段是否小于 256。

多模式和模式文件

grep -E -e 'timeout' -e 'connection refused' app.log
grep -F -f keywords.txt app.log

搜索来自用户或变量的纯文本时优先 grep -F -- "$pattern",避免内容被解释成正则或选项。

脚本中的退出码

if grep -qF -- 'ready' health.log; then
  echo 'service is ready'
else
  status=$?
  if [ "$status" -eq 1 ]; then
    echo 'not ready'
  else
    echo 'grep failed' >&2
  fi
fi

0 表示匹配,1 表示无匹配,通常 2 表示错误。不要把“没有匹配”一律记录成命令故障。

常见误区

  • ps -ef | grep java 会匹配 grep 自己,可用 pgrep -af javagrep '[j]ava'
  • grep -c 统计匹配行,不是一个行内出现多少次;需要次数可配合 grep -o ... | wc -l
  • 二进制、压缩日志需要相应工具,不能假设普通 grep 会正确处理。
  • grep -P 是实现扩展,跨 macOS/精简系统脚本不要依赖。

官方参考:GNU grep manual