文本搜索神器rg的使用教程

在大型工程项目中,传统的 grep 命令往往因性能瓶颈而显得力不从心。虽然 Ack 和 Ag (The Silver Searcher) 曾是优秀的替代品,但由 Rust 编写的 Ripgrep (rg) 凭借其卓越的性能和智能的默认配置,已成为现代开发者的首选搜索工具。

1. 工具介绍

Ripgrep (rg) 是一个面向行的搜索工具,旨在递归地在当前目录中搜索正则表达式模式。

1.1 核心特性

Ripgrep 的设计哲学是 “ 智能且快速 “。它默认启用了一系列符合开发者直觉的优化策略:

  • 智能过滤:自动读取 .gitignore 文件,忽略被排除的文件和隐藏文件。
  • 自动递归:无需像 grep 那样指定 -R 参数。
  • 高性能:基于 Rust 开发,利用多线程和 SIMD 加速,显著快于 grep、ack 和 ag。
  • 多格式支持:支持 UTF-8、UTF-16、GBK 等多种编码,以及 gzip、xz 等压缩文件。
  • 类型过滤:支持按文件类型(如 python, js)进行搜索或排除。

1.2 搜索流程可视化

下图展示了 Ripgrep 的默认文件处理逻辑,这也是其高性能的关键原因之一:

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#4F46E5', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3730A3', 'lineColor': '#6366F1', 'secondaryColor': '#10B981', 'tertiaryColor': '#F59E0B'}}}%%
flowchart TD
    Start["开始搜索"] --> Scan["扫描目录"]
    Scan --> CheckIgnore{"读取 .gitignore"}
    CheckIgnore -->|"匹配忽略规则"| Skip["跳过文件"]
    CheckIgnore -->|"未忽略"| CheckBinary{"检查二进制"}
    CheckBinary -->|"是二进制文件"| Skip
    CheckBinary -->|"是文本文件"| Match{"正则匹配内容"}
    Match -->|"匹配成功"| Output["高亮输出"]
    Match -->|"无匹配"| Next["下一个文件"]

    classDef primary fill:#4F46E5,stroke:#3730A3,color:#fff
    classDef skip fill:#9CA3AF,stroke:#4B5563,color:#fff
    classDef success fill:#10B981,stroke:#059669,color:#fff
    
    class Start,Scan,Match primary
    class Skip skip
    class Output success

1.3 进阶工具:rga

对于 PDF、E-Books、Office 文档等非纯文本文件,推荐使用 ripgrep-all (rga) 作为补充工具。

2. 安装与配置

MacOS 用户推荐使用 Homebrew 安装:

1
brew install ripgrep

建议配置别名以简化操作:

1
2
# 在 .zshrc 或 .bashrc 中添加
alias grep="rg"

3. 实战指南

3.1 基础搜索

假设当前目录下有文件 example.txt

1
2
3
test
TestCase
testing
  • 默认搜索

    1
    2
    rg 'test'
    # 输出包含 test 的行,自动高亮
  • 全词匹配 (-w)

    1
    2
    rg -w 'test'
    # 仅匹配单词 test,不匹配 testing
  • 忽略大小写 (-i)

    1
    2
    rg -i 'test'
    # 匹配 test, TestCase, testing
  • 仅显示文件名 (-l)

    1
    2
    rg -l 'test'
    # 输出: example.txt
  • 显示上下文 (-C)

    1
    2
    rg -C 2 'test'
    # 显示匹配行及其前后各 2 行

3.2 高级过滤

Ripgrep 的强大之处在于其灵活的过滤机制。

  • 指定文件类型 (-t)

    1
    2
    rg -t py 'import os'    # 仅在 Python 文件中搜索
    rg -T js 'function' # 排除 JS 文件

    Tip: 使用 rg --type-list 查看支持的所有文件类型。

  • 穿透过滤规则 (-u)
    默认情况下 rg 会忽略隐藏文件和 gitignore 规则。若需强制搜索:

    1
    2
    3
    rg -u 'secret'   # 不忽略 .gitignore
    rg -uu 'secret' # 不忽略 .gitignore 和隐藏文件
    rg -uuu 'secret' # 不忽略所有限制(包括二进制文件)
  • 正则搜索 (-e)

    1
    2
    rg -e "log.*error" -e "warn"
    # 搜索匹配正则表达式的内容

3.3 文件名查找模式

rg 也可以作为 find 命令的高效替代品,用于查找文件路径:

1
2
3
4
5
6
7
8
9
10
11
# 列出当前目录下所有将被搜索的文件(遵循 gitignore 规则)
rg --files

# 查找所有 markdown 文件
rg --files | rg '\.md$'


# 写一个 rgf 函数,非常好用
rgf () {
rg --files -uuu $2 | rg $1
}

3.4 常用选项

展示一些最重要和最常用的选项,这些选项可能会影响您定期使用 ripgrep 的方式。

-h显示 ripgrep 的浓缩帮助输出。
--help显示 ripgrep 的更长形式的帮助输出。(几乎是你在 ripgrep 的 man 页面里找到的,所以把它变成一个传呼机!)
-i/--ignore-case当搜索模式时,忽略案例差异。那就是 rg -i fast 匹配 fastfAStFAST 等。
-S/--smart-case这类似于 --ignore-case 但如果模式包含大写字母,则禁用它自己。通常将此标志放入别名或配置文件中。
-w/--word-regexp要求图案的所有匹配都被单词边界包围。也就是说,给出 pattern, the --word-regexp 标志会使 ripgrep 表现得像 pattern 实际上是 \b(?:pattern)\b
-c/--count报告总匹配行的计数。
--files打印 ripgrip _ 将要 _ 搜索的文件,但不要实际搜索它们。
-a/--text搜索二进制文件,就好像它们是纯文本一样。
-z/--search-zip搜索压缩文件 (gzip, bzip2, lzma, xz, lz4, brotli, zstd)。默认情况下这是禁用的。
-C/--context显示匹配周围的行。
--sort path强制 ripgrep 将其输出按文件名排序。(这禁用并行性,所以它可能会慢一些。)
-L/--follow在递归搜索的同时,遵循符号链接。
-M/--max-columns限制 ripgrip 打印的行的长度。
--debug显示 ripgrip 的调试输出。这对于理解为什么在搜索中可以忽略特定文件,或者 ripgrep 正在从环境中加载何种配置非常有用。

4. 编辑器集成

4.1 Vim/Neovim 集成

配合 fzf.vim 插件,可以在 Vim 中实现极致的搜索体验。

配置示例

1
2
3
4
5
6
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'

" 快捷键映射
nnoremap <leader>fo :Files<CR> " 模糊查找文件
nnoremap <leader>ff :Rg<CR> " 全局文本搜索

使用 :Rg 命令即可触发交互式搜索窗口,实时预览搜索结果。

Vim Ripgrep Integration

5. 参考资料