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。
登录后参与评论。