grep / awk / sed 文本处理速查表

速查库中文更新于 2026-11-06

TL;DR

grep 默认使用基本正则(BRE,即 -G),-E 切换为扩展正则,-F 按固定字符串匹配,-P 使用 PCRE 且与 -z 组合时属实验性。grep -m NUM 在输出 NUM 行匹配后停止,NUM 为 0 时立即停止,-1 视为无限(默认)。sed 默认自动打印模式空间,-n 抑制该行为;-i[SUFFIX] 原地编辑并在给出 SUFFIX 时备份。-n 与 p 组合是 sed 只输出指定行的标准写法。

核心选项与默认值对照

项目/要点值或说明注意事项
grep 默认正则方言-G 基本正则(BRE)未指定 -E、-F、-P 时生效
grep 扩展正则-E 或 --extended-regexp解释为 ERE
grep 固定字符串-F 或 --fixed-strings不按正则解释 PATTERNS
grep Perl 正则-P 或 --perl-regexp与 -z 组合时属实验性,可能警告未实现特性
grep 忽略大小写-i 或 --ignore-case默认不忽略,可用 --no-ignore-case 抵消脚本中的 -i
grep 反向匹配-v 或 --invert-match与 -c 同用时统计非匹配行数
grep 整词匹配-w 或 --word-regexp与 -x 同用时 -w 无效
grep 整行匹配-x 或 --line-regexp等价于给模式加 ^ 与 $
grep 最大匹配行数-m NUM,默认 -1 即无限NUM 为 0 时立即停止且不读输入
grep 仅输出匹配部分-o 或 --only-matching每个匹配部分单独一行
grep 行号与前缀-n 行号(1 起)、-b 字节偏移(0 起)、-H 文件名、-h 抑制文件名多文件搜索时 -H 为默认,单文件或标准输入时 -h 为默认
grep 文件名列表-l 有匹配的文件名、-L 无匹配的文件名-l 在首次匹配后停止扫描该文件
grep 静默与错误抑制-q 不写标准输出、-s 抑制不存在或不可读文件的错误-q 找到任一匹配即以零状态立即退出
grep 空字节分隔-Z 或 --null文件名后输出 ASCII NUL 而非换行
sed 抑制自动打印-n、--quiet、--silent常与 p 组合只打印指定行
sed 原地编辑-i[SUFFIX] 或 --in-place[=SUFFIX]给出 SUFFIX 时生成备份
sed 扩展正则-E、-r、--regexp-extended可移植写法用 POSIX -E
sed 脚本来源-e script、-f script-file两者都未给出时,第一个非选项参数作为脚本
sed 文件独立处理-s 或 --separate行号按文件分别累计而非跨文件连续
sed 空字节分隔-z 或 --null-data以 NUL 字符分隔行
sed 替换命令s/regexp/replacement/replacement 中 & 指代整个匹配,\1 到 \9 指代子表达式
sed 地址范围addr1,addr2addr1 匹配行总被接受;addr2 为正则时不测试 addr1 匹配的那一行
sed 地址取反地址后加 !命令仅在地址不匹配时执行

常用操作与命令

grep:按模式类型与输出形态选择选项

先确定模式类型:普通文本用 -F 避免正则元字符干扰,需要 +、?、{} 等写法用 -E,需要 PCRE 特性用 -P。再确定输出形态:只要计数用 -c,只要匹配片段用 -o,只要文件名用 -l 或 -L,脚本判断用 -q。-m NUM 控制提前停止,-n、-b、-H 控制行前缀。

bash
# 递归搜索当前目录,忽略大小写,输出文件名与行号
grep -rni --include='*.conf' 'timeout' .

# 固定字符串匹配,只输出匹配片段,最多 5 行
grep -F -o -m 5 'ERROR_CODE' app.log

# 列出包含匹配的文件名,以 NUL 分隔,便于 xargs -0 处理
grep -lZ 'TODO' src/*.c

sed:替换、删除与按地址范围处理

sed 对输入只做一遍扫描。默认自动打印模式空间,-n 关闭后需显式 p。替换用 s///,删除用 d,整行替换用 c\,字符转换用 y///。地址可以是行号、first~step 步进或正则;两个地址用逗号构成范围,! 取反。

bash
# 原地编辑并保留 .bak 备份,把行首的 foo 替换为 bar
sed -i.bak 's/^foo/bar/' config.txt

# 只打印第 10 到 20 行
sed -n '10,20p' input.txt

# 删除空行,并删除匹配 deprecated 的行
sed -e '/^$/d' -e '/deprecated/d' notes.md

组合使用:grep 过滤后交给 sed 或 awk

grep 的 -o 输出每行一个匹配片段,适合作为下游的输入。sed 的 -s 让多个文件的行号分别累计,-z 处理 NUL 分隔数据。管道中若上游是 gzip 解压流,可用 --label 让 grep 以指定文件名显示标准输入来源。

bash
# 从日志中提取匹配片段,再统一替换分隔符
grep -o 'user=[^ ]*' access.log | sed 's/^user=//'

# 解压流搜索时用 --label 标注来源文件名
gzip -cd foo.gz | grep --label=foo -H 'some pattern'

常见问题

grep 的 -E、-F、-P 有什么区别?

-E 把 PATTERNS 解释为扩展正则(ERE),-F 按固定字符串解释、不当作正则,-P 解释为 Perl 兼容正则(PCRE)。未指定任何一项时默认是 -G 基本正则(BRE)。-P 与 -z 组合时属实验性,可能警告未实现特性。

grep -m 0 和 -m -1 分别是什么行为?

-m 0 让 grep 立即停止、不读取输入;-m -1 被视为无限,grep 不会因匹配行数停止,这也是默认值。与 -c 同用时输出计数不超过 NUM;与 -v 同用时在输出 NUM 行非匹配行后停止。

sed 的 -i 会不会破坏原文件?

-i[SUFFIX] 是原地编辑,给出 SUFFIX 时会生成备份,例如 -i.bak 保留原文件副本。未给出 SUFFIX 时不生成备份,原内容被直接替换。

sed 地址范围中 addr2 是正则时有什么特殊规则?

addr1 匹配的那一行总会被接受,即使 addr2 指向更早的行;并且当 addr2 是正则时,不会对 addr1 匹配的那一行做测试。地址后加 ! 表示命令仅在地址不匹配时执行。

grep -w 和 -x 能一起用吗?

不能指望两者叠加生效:-w 在同时指定 -x 时无效。-w 要求匹配子串位于行首或前面是非单词构成字符、且位于行尾或后面是非单词构成字符;-x 要求整个匹配恰好等于整行。

来源