ripgrep(rg)替代 grep:尊重 .gitignore + 自动忽略二进制 + 快 10 倍

rg 是 ripgrep 的命令行工具。比 grep -r 快一个数量级(Rust + SIMD),
默认行为更符合代码库搜索的预期:跳过 .git、尊重 .gitignore
跳过二进制文件、自动多线程。

安装

sudo apt install -y ripgrep         # Debian 11+ / Ubuntu 20.04+
brew install ripgrep                # macOS
choco install ripgrep               # Windows
rg --version

最基础

rg pattern              # 在当前目录递归搜 pattern
rg pattern src/         # 在 src/ 里搜
rg -i pattern           # 大小写不敏感
rg -w word              # 整词匹配
rg -v 'never'           # 反向(不含的行)
rg -F 'a.b.c'           # 字面字符串(不当 regex)

输出格式:

src/utils/string.py
12: def normalize(s: str) -> str:
14:     return s.strip().lower()

文件名 + 行号 + 高亮。

文件类型筛选

rg pattern -t py        # 只在 Python 文件搜
rg pattern -T md        # 排除 Markdown
rg pattern -g '*.tsx'   # glob 匹配
rg pattern -g '!**/node_modules/**'   # glob 排除

rg --type-list          # 列所有已知文件类型

-t-T 让命令行干净得多——rg -t py error vs
grep -r --include='*.py' error .

显示前后行(context)

rg pattern -A 3         # after 3 行
rg pattern -B 3         # before 3 行
rg pattern -C 3         # context 前后各 3 行

跟 grep 完全一样的参数。

只列文件名

rg -l pattern           # 只列匹配的文件名
rg --files-without-match pattern   # 反过来,列不匹配的文件

-l 配合 fzf / xargs 极常用:

# 编辑所有匹配的文件
vim $(rg -l 'TODO')

替换(dry-run + 实际改)

# dry-run:只显示替换效果,不写入
rg 'old_name' --replace 'new_name'

# 真的批量替换:rg 找出 + sed 改
rg -l 'old_name' | xargs sed -i 's/old_name/new_name/g'
# macOS 上 sed -i '' '...'

或者用 sd(rust 写的 sed 替代):

rg -l 'old_name' | xargs sd 'old_name' 'new_name'

输出 JSON(pipeline 友好)

rg --json pattern src/ | head
# {"type":"begin","data":{"path":{"text":"src/foo.py"}}}
# {"type":"match","data":{"path":...,"lines":...,"line_number":12,...}}
# {"type":"end",...}

让别的工具处理结构化输出。

通用预设:~/.ripgreprc

# ~/.ripgreprc
--smart-case
--max-columns=200
--colors=line:fg:yellow
--colors=path:fg:blue
--type-add=web:*.{html,css,js,jsx,ts,tsx,vue}
--type-add=md:*.{md,markdown,mdx}
echo 'export RIPGREP_CONFIG_PATH=~/.ripgreprc' >> ~/.bashrc

之后 rg pattern 自动用这套默认。

与 grep 对比

任务 grep rg
在仓库找 TODO grep -r --include='*.py' TODO . rg -t py TODO
跳过 .git / node_modules 要手动 --exclude-dir 自动
二进制文件 默认搜(输出乱码) 自动跳过
速度(100k LOC) 几秒 < 0.5s
默认大小写 区分 smart-case (有大写=区分)

grep 仍然是 POSIX 工具,远程小机器没 rg 时用。日常本地 / CI 用 rg。

与 fzf 联用

# 模糊搜代码内容
rg . --line-number --no-heading --color=always \
  | fzf --ansi --delimiter=':' \
        --preview 'bat --color=always {1} --highlight-line {2}'

写成函数(前面 fzf 那篇有提到)。

VSCode 内部用了它

VSCode 的全局搜索(Ctrl-Shift-F)底层就是 ripgrep。任何用 rg 直接命令行的
都和 IDE 搜索一致体验。

性能:为什么这么快

  • 用 Rust 写 + Aho-Corasick / RE2 / SIMD
  • 多线程:每个文件并行搜
  • mmap:大文件 zero-copy
  • gitignore 解析:跳过整个子树而不是访问每个文件
  • 二进制检测:发现 NUL 字节立即跳过整个文件

边界 / 别用 rg 的场合

  • 单文件的复杂正则:grep -P 的 PCRE 比 rg 默认的 Rust regex 更全
    (lookbehind 等)。rg 加 -P 也能用 PCRE2,但需要 build 时打开特性。
  • 流式(stdin)+ 极简:grep 在 docker shell / 嵌入式环境永远可用。
  • 颜色输出走 pipeline:rg 默认看到 stdout 不是 tty 就关闭颜色,
    和别的工具兼容。

踩过的坑

  • 想搜 .git 里的东西时 rg 默认跳过 → 加 -uu("unrestricted" 二次:
    搜隐藏 + 不尊重 .gitignore + 二进制)。
  • .gitignore*.log 时 rg 不会搜日志文件 —— 通常正确,但调试时
    忘了为什么没结果。rg -u pattern 一次性绕过 ignore 规则。
  • 重定向到文件后颜色没了:rg --color=always pattern | less -R 强制保留颜色。
  • 中文 / 非 ASCII 搜索:rg 默认 UTF-8 兼容;老 BOM / GBK 文件需要
    --encoding gbk
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。