ripgrep(命令行 rg)是一款用 Rust 编写的递归代码搜索工具。它默认遵守 .gitignore、自动跳过隐藏文件与二进制文件,搜索速度常常比传统 grep 快一个数量级。对于每天要在大型代码库里翻找符号、TODO、配置项的开发者来说,换上 ripgrep 几乎是无成本的性能升级。
一个常见的场景是:你在仓库存放了一个 50 万行的单体服务,依赖目录 node_modules 里还有几万个文件。用 grep -r "TimeoutException" 会先把 node_modules 翻个底朝天,屏幕刷满噪音、十几秒才出结果;而 rg "TimeoutException" 往往在 1 秒内给出干净的答案。差别不是“快一点”,而是“能不能忍着用它”。
一、为什么需要 ripgrep
很多团队还在用 grep -r 满仓库搜,但 grep 有几个天然短板:它不会主动忽略 .gitignore 里声明的文件,也不会跳过 node_modules 这类巨型目录,结果既慢又产生大量噪音。ripgrep 的设计哲学恰恰相反——“默认就做对的事”。
| 工具 | 默认忽略 .gitignore | 默认跳过二进制 | 并行遍历 | 语言 | 核心亮点 |
| grep | 否 | 否 | 否 | C | 系统自带、无需安装 |
| ack | 否 | 是 | 否 | Perl | 专为代码优化的正则 |
| ag | 是 | 是 | 是 | C | ripgrep 的前身思路 |
| ripgrep | 是 | 是 | 是 | Rust | 最快、零配置、安全正则引擎 |
ripgrep 之所以快,关键在于三点:并行递归目录遍历、Rust regex 引擎(基于有限自动机,不会 catastrophic backtracking)、以及利用 SIMD 指令加速字面量匹配。
二、安装:一条命令搞定
几乎所有包管理器都已收录 ripgrep,按你的平台选一条:
# macOS
brew install ripgrep
# Ubuntu 22.04+ / Debian
sudo apt install ripgrep
# Arch
sudo pacman -S ripgrep
# Windows (scoop)
scoop install ripgrep
# 通用:Rust 工具链
cargo install ripgrep
# 或直接从 GitHub Releases 下载预编译二进制
# https://github.com/BurntSushi/ripgrep/releases
装好后用 rg --version 验证,再跑 rg --type-list 可以看到它原生支持的两百多种文件类型(py、js、go、rs、md……)。
三、最常用命令:10 秒上手
ripgrep 的默认行为已经足够好,下面这几条覆盖了 80% 的日常场景:
# 递归搜索 "fn handle"(默认忽略 gitignore / 二进制 / 隐藏文件)
rg "fn handle"
# 不区分大小写
rg -i "TODO"
# 显示行号(默认已显示;-h 仅输出内容不含文件名)
rg -n "error" src/
# 只列出命中文件(配合 fzf 做二次过滤非常爽)
rg -l "deprecated"
# 统计每个文件的匹配数
rg -c "panic"
# 只看命中文件总数
rg -l "unwrap" | wc -l
如果你已经在用 fzf 模糊查找 重塑终端工作流,rg -l 输出的文件列表直接管道给 fzf,就能瞬间得到一个可交互的“搜索结果浏览器”。
四、按文件类型与目录过滤
ripgrep 的类型系统让“只在 Python 文件里搜”变成一行命令,不必手写复杂 glob:
# 只在 Python 文件里搜
rg -t py "import os"
# 排除某种类型(例如跳过测试)
rg -T test "connect"
# 自定义 glob:只看 src 下、排除 min.js
rg -g 'src/**' -g '!*.min.js' "fetch"
# 强制搜索隐藏文件(默认跳过 .git、.env 等)
rg --hidden "api_key"
# 连 gitignore 忽略的文件也搜(慎用,会慢)
rg -u "secret" # -u 搜隐藏;-uu 搜忽略;-uuu 搜全部含二进制
五、替换与结构化输出
5.1 用 -r 做整库重命名式替换预览
ripgrep 本身不写文件(那是 sed 的活),但 -r 可以输出“替换后”的内容,方便你先确认再落地:
# 把 foo 改成 bar,只预览替换结果(不修改文件)
rg -r "bar" "foo" --no-heading
# 配合 sed -i 真正落地(先 rg 确认范围,再 sed 执行)
rg -l "old_api" | xargs sed -i '' 's/old_api/new_api/g'
5.2 用 –json 接入 jq 做自动化
--json 让每条匹配变成一行 JSON,非常适合在脚本里二次处理:
# 找出所有 TODO 并输出文件路径 + 行号
rg --json "TODO" --no-heading | jq -r 'select(.type=="match") | .data.path.text + ":" + (.data.lines.text|tostring)'
六、进阶:正则、上下文与性能
# 固定字符串搜索(把模式当字面量,避免正则元字符报错)
rg -F "a.b.c" # 只匹配字面的 a.b.c
# 前后各 3 行上下文
rg -C 3 "panic"
# 整词匹配(边界)
rg -w "log"
# 看看这次搜索花在哪:文件数、匹配数、耗时
rg --stats "serialize"
ripgrep 的正则基于有限自动机,遇到 (a+)+ 这类“灾难性回溯”模式也不会卡死——这是它相对很多 PCRE 引擎的安全优势。需要更激进的 PCRE2 语法时,可加 -P(编译时启用了 PCRE2 的版本才支持)。
七、在 CI 与编辑器里用起来
ripgrep 不只是本地利器,它早已是很多工具的“心脏”。例如 VS Code 的全局搜索 底层就是 ripgrep——你在编辑器里按 Ctrl/Cmd+Shift+F 搜的每一行,背后都是 rg 在跑。理解了这一点,你在终端和编辑器里的搜索行为就能完全对齐。
在 GitHub Actions 流水线 里,ripgrep 也能做轻量级“规范门禁”:
# 在 CI 中禁止遗留的调试代码合入
- name: Lint guard
run: |
if rg -l "console.log|debugger|TODO:REMOVE" src/; then
echo "发现疑似调试代码,请清理后再提交"
exit 1
fi
八、ripgrep 与 git:天生一对
ripgrep 默认就“懂” git:它会读取 .gitignore、.git/info/exclude 以及全局 gitignore,自动把第三方依赖和构建产物排除在搜索范围之外。这意味着你在项目根目录直接敲 rg "xxx",结果天然干净,不会像 grep 那样把 node_modules 里的几万个文件也翻一遍。如果你就是想搜被忽略的文件(比如确认某个密钥有没有意外提交),加 -u 即可逐层放开;反之想完全无视所有忽略规则、连隐藏文件一起扫,用 -uuu。
# 默认忽略 .gitignore 中的文件(不会进 node_modules)
rg "api_key"
# 额外搜索隐藏文件
rg -u "api_key"
# 搜索一切文件(含被 ignore 的、含二进制)
rg -uuu "api_key"
# 在 git 仓库里只搜已跟踪文件
git ls-files | rg "test"
九、固化配置:~/.ripgreprc
每次都敲一长串参数很烦。ripgrep 支持读取 RIPGREP_CONFIG_PATH 指向的配置文件,把常用开关固化下来,团队新人拉一份配置就能获得一致的搜索体验:
# ~/.ripgreprc
--smart-case # 含大写才区分大小写,全小写则忽略大小写
--line-number
--color=auto
# 自定义类型:把 vue 也算作前端文件
--type-add
web:*.{html,js,ts,vue,css}
设置环境变量 export RIPGREP_CONFIG_PATH="$HOME/.ripgreprc" 后,rg 会自动套用这些选项,日常调用只需写最精简的模式即可。
十、一次真实重构的搜索流
假设你要给一个老服务做“日志组件统一”重构,流程大概是:先 rg -l "console.log" 圈出所有散落的打印点,再用 rg -t ts -C 2 "console.log" 逐个看上下文,确认后批量改成统一 logger;最后用 rg -l "console.log" 反过来验证“零残留”。这一套“圈范围 → 看上下文 → 验证清零”的闭环,正是 ripgrep 最舒服的用法。
# 1) 圈出范围
rg -l "console.log" src/
# 2) 看上下文(前后 2 行)
rg -t ts -C 2 "console.log" src/
# 3) 替换并验证清零
rg -l "console.log" src/ | xargs sed -i '' 's/console\.log/logger.info/g'
rg -l "console.log" src/ # 期望无输出
十一、常见坑与排雷 checklist
- 搜不到?先确认是不是被 .gitignore 或隐藏规则过滤了,加
-u(甚至-uuu)重试。 - 想搜中文/Unicode?ripgrep 默认 UTF-8,直接搜即可;文件编码非 UTF-8 时用
--encoding。 - 误以为 rg 会改文件?rg 只读不写,
-r只是“输出替换结果”,真正改写请用 sed/IDE。 - 正则不生效?注意 shell 引号;含
$、*等建议用单引号包裹模式。 - 性能异常慢?多半是
-u穿透了 node_modules 之类巨型目录,用-g收缩范围。
结语
ripgrep 是典型的“装上就回不去”的工具:零配置、速度快、默认行为符合直觉。把它和 后端命令行效率工具 里的其他利器组合,你的终端检索效率会直接上一个台阶。今天就可以在常用项目里跑一次 rg "TODO",看看那些被遗忘的待办。




