BurntSushi/ripgrep
GitHub: BurntSushi/ripgrep
一款用 Rust 编写的高性能递归搜索工具,支持正则表达式匹配并自动遵守 gitignore 规则。
Stars: 60787 | Forks: 2407
## ripgrep (rg)
ripgrep 是一个面向行的搜索工具,它递归搜索当前目录以查找正则表达式模式。默认情况下,ripgrep 会遵守 gitignore 规则并自动跳过隐藏文件/目录和二进制文件。(要默认禁用所有自动过滤,请使用 `rg -uuu`。)ripgrep 在 Windows、macOS 和 Linux 上提供一流的支持,并且每次[发布](https://github.com/BurntSushi/ripgrep/releases)都提供二进制下载。ripgrep 类似于其他流行的搜索工具,如 The Silver Searcher、ack 和 grep。
[](https://github.com/BurntSushi/ripgrep/actions)
[](https://crates.io/crates/ripgrep)
[](https://repology.org/project/ripgrep/badges)
双重许可 under MIT 或 [UNLICENSE](https://unlicense.org)。
### 更新日志 (CHANGELOG)
请参阅 [CHANGELOG](CHANGELOG.md) 获取发布历史。
### 文档快速链接
* [安装](#installation)
* [用户指南](GUIDE.md)
* [常见问题解答](FAQ.md)
* [正则表达式语法](https://docs.rs/regex/1/regex/#syntax)
* [配置文件](GUIDE.md#configuration-file)
* [Shell 补全](FAQ.md#complete)
* [构建](#building)
* [翻译](#translations)
### 搜索结果截图
[](https://burntsushi.net/stuff/ripgrep1.png)
### 比较工具的快速示例
此示例在(运行 `make defconfig && make -j8` 后)整个 [Linux 内核源码树](https://github.com/BurntSushi/linux)中搜索 `[A-Z]+_SUSPEND`,其中所有匹配项必须是单词。计时是在配备 Intel i9-12900K 5.2 GHz 的系统上收集的。
请记住,单一基准测试永远不够!请参阅我关于 ripgrep 的[博客文章](https://blog.burntsushi.net/ripgrep/),以获取包含更多基准测试和分析的非常详细的比较。
| Tool | Command | Line count | Time |
| ---- | ------- | ---------- | ---- |
| ripgrep (Unicode) | `rg -n -w '[A-Z]+_SUSPEND'` | 536 | **0.082s** (1.00x) |
| [hypergrep](https://github.com/p-ranav/hypergrep) | `hgrep -n -w '[A-Z]+_SUSPEND'` | 536 | 0.167s (2.04x) |
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `git grep -P -n -w '[A-Z]+_SUSPEND'` | 536 | 0.273s (3.34x) |
| [The Silver Searcher](https://github.com/ggreer/the_silver_searcher) | `ag -w '[A-Z]+_SUSPEND'` | 534 | 0.443s (5.43x) |
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep -r --ignore-files --no-hidden -I -w '[A-Z]+_SUSPEND'` | 536 | 0.639s (7.82x) |
| [git grep](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=C git grep -E -n -w '[A-Z]+_SUSPEND'` | 536 | 0.727s (8.91x) |
| [git grep (Unicode)](https://www.kernel.org/pub/software/scm/git/docs/git-grep.html) | `LC_ALL=en_US.UTF-8 git grep -E -n -w '[A-Z]+_SUSPEND'` | 536 | 2.670s (32.70x) |
| [ack](https://github.com/beyondgrep/ack3) | `ack -w '[A-Z]+_SUSPEND'` | 2677 | 2.935s (35.94x) |
这是在上述相同语料库上的另一个基准测试,它忽略 gitignore 文件并使用白名单进行搜索。语料库与前一个基准测试相同,传递给每个命令的标志确保它们执行同等的工作:
| Tool | Command | Line count | Time |
| ---- | ------- | ---------- | ---- |
| ripgrep | `rg -uuu -tc -n -w '[A-Z]+_SUSPEND'` | 447 | **0.063s** (1.00x) |
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep -r -n --include='*.c' --include='*.h' -w '[A-Z]+_SUSPEND'` | 447 | 0.607s (9.62x) |
| [GNU grep](https://www.gnu.org/software/grep/) | `grep -E -r -n --include='*.c' --include='*.h' -w '[A-Z]+_SUSPEND'` | 447 | 0.674s (10.69x) |
现在我们将转向搜索单个大文件。这是在缓存于内存中的文件(~13GB,[`OpenSubtitles.raw.en.gz`](http://opus.nlpl.eu/download.php?f=OpenSubtitles/v2018/mono/OpenSubtitles.raw.en.gz),已解压)上 ripgrep、ugrep 和 GNU grep 之间的直接比较:
| Tool | Command | Line count | Time |
| ---- | ------- | ---------- | ---- |
| ripgrep (Unicode) | `rg -w 'Sherlock [A-Z]\w+'` | 7882 | **1.042s** (1.00x) |
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep -w 'Sherlock [A-Z]\w+'` | 7882 | 1.339s (1.28x) |
| [GNU grep (Unicode)](https://www.gnu.org/software/grep/) | `LC_ALL=en_US.UTF-8 egrep -w 'Sherlock [A-Z]\w+'` | 7882 | 6.577s (6.31x) |
在上面的基准测试中,传递 `-n` 标志(用于显示行号)将 ripgrep 的时间增加到 `1.664s`,GNU grep 增加到 `9.484s`。ugrep 的时间不受 `-n` 存在与否的影响。
不过要注意性能悬崖:
| Tool | Command | Line count | Time |
| ---- | ------- | ---------- | ---- |
| ripgrep (Unicode) | `rg -w '[A-Z]\w+ Sherlock [A-Z]\w+'` | 485 | **1.053s** (1.00x) |
| [GNU grep (Unicode)](https://www.gnu.org/software/grep/) | `LC_ALL=en_US.UTF-8 grep -E -w '[A-Z]\w+ Sherlock [A-Z]\w+'` | 485 | 6.234s (5.92x) |
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep -w '[A-Z]\w+ Sherlock [A-Z]\w+'` | 485 | 28.973s (27.51x) |
当在大文件中搜索没有任何字面量优化机会的模式时,性能可能会全面急剧下降:
| Tool | Command | Line count | Time |
| ---- | ------- | ---------- | ---- |
| ripgrep | `rg '[A-Za-z]{30}'` | 6749 | **15.569s** (1.00x) |
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep -E '[A-Za-z]{30}'` | 6749 | 21.857s (1.40x) |
| [GNU grep](https://www.gnu.org/software/grep/) | `LC_ALL=C grep -E '[A-Za-z]{30}'` | 6749 | 32.409s (2.08x) |
| [GNU grep (Unicode)](https://www.gnu.org/software/grep/) | `LC_ALL=en_US.UTF-8 grep -E '[A-Za-z]{30}'` | 6795 | 8m30s (32.74x) |
最后,高匹配计数也往往会导致性能下降并抹平工具之间的差异(因为通常来说,性能取决于处理匹配项的速度,而不是用于检测匹配项的算法):
| Tool | Command | Line count | Time |
| ---- | ------- | ---------- | ---- |
| ripgrep | `rg the` | 83499915 | **6.948s** (1.00x) |
| [ugrep](https://github.com/Genivia/ugrep) | `ugrep the` | 83499915 | 11.721s (1.69x) |
| [GNU grep](https://www.gnu.org/software/grep/) | `LC_ALL=C grep the` | 83499915 | 15.217s (2.19x) |
### 为什么我应该使用 ripgrep?
* 它可以替代许多由其他搜索工具服务的用例,因为它包含了它们的大部分功能并且通常更快。(有关 ripgrep 是否能真正替代 grep 的更多详细信息,请参阅 [FAQ](FAQ.md#posix4ever)。)
* 与其他专门用于代码搜索的工具一样,ripgrep 默认为[递归搜索](GUIDE.md#recursive-search)并进行[自动过滤](GUIDE.md#automatic-filtering)。也就是说,ripgrep 不会搜索被 `.gitignore`/`.ignore`/`.rgignore` 文件忽略的文件,不会搜索隐藏文件,也不会搜索二进制文件。可以使用 `rg -uuu` 禁用自动过滤。
* ripgrep 可以[搜索特定类型的文件](GUIDE.md#manual-filtering-file-types)。例如,`rg -tpy foo` 将您的搜索限制在 Python 文件,而 `rg -Tjs foo` 从您的搜索中排除 JavaScript 文件。可以通过自定义匹配规则教 ripgrep 识别新的文件类型。
* ripgrep 支持 `grep` 中的许多功能,例如显示搜索结果的上下文、搜索多个模式、用颜色高亮匹配项以及完整的 Unicode 支持。与 GNU grep 不同,ripgrep 在支持 Unicode(始终开启)的同时保持快速。
* ripgrep 具有将其 regex 引擎切换为使用 PCRE2 的可选支持。除其他外,这使得在您的模式中使用 look-around 和反向引用成为可能,这些在 ripgrep 的默认 regex 引擎中不受支持。可以使用 `-P/--pcre2`(始终使用 PCRE2)或 `--auto-hybrid-regex`(仅在需要时使用 PCRE2)启用 PCRE2 支持。通过 `--engine (default|pcre2|auto)` 选项提供了一种替代语法。
* ripgrep 具有[基本的替换支持](GUIDE.md#replacements),允许根据匹配的内容重写输出。
* ripgrep 支持搜索 UTF-8 以外[文本编码的文件](GUIDE.md#file-encoding),例如 UTF-16、latin-1、GBK、EUC-JP、Shift_JIS 等。(提供了一些自动检测 UTF-16 的支持。其他文本编码必须使用 `-E/--encoding` 标志明确指定。)
* ripgrep 支持使用 `-z/--search-zip` 标志搜索以通用格式(brotli、bzip2、gzip、lz4、lzma、xz 或 zstandard)压缩的文件。
* ripgrep 支持[任意输入预处理过滤器](GUIDE.md#preprocessor),例如 PDF 文本提取、较少支持的解压、解密、自动编码检测等。
* ripgrep 可以通过[配置文件](GUIDE.md#configuration-file)进行配置。
换句话说,如果您喜欢速度、默认过滤、更少的 bug 和 Unicode 支持,请使用 ripgrep。
### 为什么我不应该使用 ripgrep?
尽管最初不想将所有功能都添加到 ripgrep 中,但随着时间的推移,ripgrep 已经支持了大多数其他文件搜索工具中的功能。这包括搜索跨越多行的结果,以及 PCRE2 的选择加入支持,后者提供了 look-around 和反向引用支持。
此时,不使用 ripgrep 的主要原因可能包括以下一项或多项:
* 您需要一个可移植且普遍存在的工具。虽然 ripgrep 可在 Windows、macOS 和 Linux 上运行,但它并不普遍,也不符合任何标准(如 POSIX)。最适合这项工作的工具是老旧的 grep。
* 仍然存在此 README 中未列出的某些其他功能(或 bug),您依赖的这些功能在另一个工具中存在,但在 ripgrep 中不存在。
* 存在某种性能边缘情况,ripgrep 在该情况下表现不佳,而另一个工具表现良好。(请提交 bug 报告!)
* ripgrep 无法安装在您的机器上,或者不适用于您的平台。(请提交 bug 报告!)
### 它真的比其他所有东西都快吗?
一般来说,是的。包含详细分析的大量基准测试[可在我的博客上找到](https://blog.burntsushi.net/ripgrep/)。
总而言之,ripgrep 之所以快是因为:
* 它构建在 [Rust 的 regex 引擎](https://github.com/rust-lang/regex)之上。Rust 的 regex 引擎使用有限自动机、SIMD 和积极的字面量优化来使搜索非常快。(可以通过 `-P/--pcre2` 标志选择加入 PCRE2 支持。)
* Rust 的 regex 库通过将 UTF-8 解码直接构建到其确定性有限自动机引擎中,从而在保持完整 Unicode 支持的同时维持性能。
* 它使用内存映射或通过中间缓冲区增量进行搜索。前者更适合单文件,后者更适合大目录。ripgrep 会自动为您选择最佳的搜索策略。
* 使用 [`RegexSet`](https://docs.rs/regex/1/regex/struct.RegexSet.html) 应用 `.gitignore` 文件中的忽略模式。这意味着单个文件路径可以同时匹配多个 glob 模式。
* 它使用无锁并行递归目录迭代器,由 [`crossbeam`](https://docs.rs/crossbeam) 和 [`ignore`](https://docs.rs/ignore) 提供。
### 功能比较
[ack](https://beyondgrep.com/) 的作者 Andy Lester 发布了一个比较 ack、ag、git-grep、GNU grep 和 ripgrep 功能的优秀表格:https://beyondgrep.com/feature-comparison/
请注意,ripgrep 最近增加了一些重要的新功能,这些功能尚未出现在 Andy 的表格中。这包括但不限于配置文件、passthru、搜索压缩文件的支持、多行搜索以及通过 PCRE2 的选择加入高级 regex 支持。
### 演练场 (Playground)
如果您想在安装前试用 ripgrep,有一个非官方的[演练场](https://codapi.org/ripgrep/)和[交互式教程](https://codapi.org/try/ripgrep/)。
如果您对此有任何疑问,请在[教程仓库](https://github.com/nalgeon/tryxinyminutes)中开一个 issue。
### 安装
ripgrep 的二进制文件名为 `rg`。
**[ripgrep 的预编译二进制文件存档可用于 Windows、macOS 和 Linux。](https://github.com/BurntSushi/ripgrep/releases)** Linux 和 Windows 二进制文件是静态可执行文件。建议未在下方明确提及的平台的用户下载这些存档之一。
如果您是 **macOS Homebrew** 或 **Linuxbrew** 用户,则可以从 homebrew-core 安装 ripgrep:
```
$ brew install ripgrep
```
如果您是 **MacPorts** 用户,则可以从[官方 ports](https://www.macports.org/ports.php?by=name&substr=ripgrep) 安装 ripgrep:
```
$ sudo port install ripgrep
```
如果您是 **Windows Chocolatey** 用户,则可以从[官方仓库](https://chocolatey.org/packages/ripgrep) 安装 ripgrep:
```
$ choco install ripgrep
```
如果您是 **Windows Scoop** 用户,则可以从[官方 bucket](https://github.com/ScoopInstaller/Main/blob/master/bucket/ripgrep.json) 安装 ripgrep:
```
$ scoop install ripgrep
```
如果您是 **Windows Winget** 用户,则可以从 [winget-pkgs](https://github.com/microsoft/winget-pkgs/tree/master/manifests/b/BurntSushi/ripgrep) 仓库安装 ripgrep:
```
$ winget install BurntSushi.ripgrep.MSVC
```
如果您是 **Arch Linux** 用户,则可以从官方仓库安装 ripgrep:
```
$ sudo pacman -S ripgrep
```
如果您是 **Gentoo** 用户,则可以从[官方仓库](https://packages.gentoo.org/packages/sys-apps/ripgrep) 安装 ripgrep:
```
$ sudo emerge sys-apps/ripgrep
```
如果您是 **Fedora** 用户,则可以从官方仓库安装 ripgrep。
```
$ sudo dnf install ripgrep
```
如果您是 **openSUSE** 用户,ripgrep 包含在 **openSUSE Tumbleweed** 和自 15.1 以来的 **openSUSE Leap** 中。
```
$ sudo zypper install ripgrep
```
如果您是 **CentOS Stream 10** 用户,则可以从 [EPEL](https://docs.fedoraproject.org/en-US/epel/getting-started/) 仓库安装 ripgrep:
```
$ sudo dnf config-manager --set-enabled crb
$ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
$ sudo dnf install ripgrep
```
如果您是 **Red Hat 10** 用户,则可以从 [EPEL](https://docs.fedoraproject.org/en-US/epel/getting-started/) 仓库安装 ripgrep:
```
$ sudo subscription-manager repos --enable codeready-builder-for-rhel-10-$(arch)-rpms
$ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
$ sudo dnf install ripgrep
```
如果您是 **Rocky Linux 10** 用户,则可以从 [EPEL](https://docs.fedoraproject.org/en-US/epel/getting-started/) 仓库安装 ripgrep:
```
$ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
$ sudo dnf install ripgrep
```
如果您是 **Nix** 用户,则可以从 [nixpkgs](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ri/ripgrep/package.nix) 安装 ripgrep:
```
$ nix-env --install ripgrep
```
如果您是 **Flox** 用户,则可以按如下方式安装 ripgrep:
```
$ flox install ripgrep
```
如果您是 **Guix** 用户,则可以从官方软件包集合安装 ripgrep:
```
$ guix install ripgrep
```
如果您是 **Debian** 用户(或 **Ubuntu** 等 Debian 衍生版本的用户),则可以使用每次 [ripgrep 发布](https://github.com/BurntSushi/ripgrep/releases)中提供的二进制 `.deb` 文件进行安装。
```
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep_14.1.1-1_amd64.deb
$ sudo dpkg -i ripgrep_14.1.1-1_amd64.deb
```
如果您运行的是 Debian stable,ripgrep [由 Debian 官方维护](https://tracker.debian.org/pkg/rust-ripgrep),尽管其版本可能比上一步中提供的 `deb` 软件包更旧。
```
$ sudo apt-get install ripgrep
```
如果您是 **Ubuntu Cosmic (18.10)**(或更新版本)用户,可以使用与 Debian 相同的打包方式[安装](https://launchpad.net/ubuntu/+source/rust-ripgrep) ripgrep:
```
$ sudo apt-get install ripgrep
```
(注意:Ubuntu 上也有各种 ripgrep 的 snaps,但似乎没有一个能正常工作,并且产生了许多我不知道如何修复也没有时间修复的非常奇怪的 bug 报告。因此,它不再是被推荐的安装选项。)
如果您是 **ALT** 用户,则可以从[官方仓库](https://packages.altlinux.org/en/search?name=ripgrep) 安装 ripgrep:
```
$ sudo apt-get install ripgrep
```
如果您是 **FreeBSD** 用户,则可以从[官方 ports](https://www.freshports.org/textproc/ripgrep/) 安装 ripgrep:
```
$ sudo pkg install ripgrep
```
如果您是 **OpenBSD** 用户,则可以从[官方 ports](https://openports.se/textproc/ripgrep) 安装 ripgrep:
```
$ doas pkg_add ripgrep
```
如果您是 **NetBSD** 用户,则可以从 [pkgsrc](https://pkgsrc.se/textproc/ripgrep) 安装 ripgrep:
```
$ sudo pkgin install ripgrep
```
如果您是 **Haiku x86_64** 用户,则可以从[官方 ports](https://github.com/haikuports/haikuports/tree/master/sys-apps/ripgrep) 安装 ripgrep:
```
$ sudo pkgman install ripgrep
```
如果您是 **Haiku x86_gcc2** 用户,则可以使用 x86 辅助架构构建从与 Haiku x86_64 相同的 port 安装 ripgrep:
```
$ sudo pkgman install ripgrep_x86
```
如果您是 **Void Linux** 用户,则可以从[官方仓库](https://voidlinux.org/packages/?arch=x86_64&q=ripgrep) 安装 ripgrep:
```
$ sudo xbps-install -Syv ripgrep
```
如果您是 **Rust 程序员**,可以使用 `cargo` 安装 ripgrep。
* 请注意,ripgrep 支持的最低 Rust 版本是 **1.85.0**,尽管 ripgrep 可能适用于旧版本。
* 请注意,二进制文件可能比预期的大,因为它包含调试符号。这是有意为之。要删除调试符号从而减小文件大小,请对二进制文件运行 `strip`。
```
$ cargo install ripgrep
```
或者,可以使用 [`cargo binstall`](https://github.com/cargo-bins/cargo-binstall) 直接从 GitHub 安装 ripgrep 二进制文件:
```
$ cargo binstall ripgrep
```
### 构建
ripgrep 是用 Rust 编写的,因此您需要获取 [Rust 安装](https://www.rust-lang.org/)才能编译它。
ripgrep 使用 Rust 1.85.0 (stable) 或更新版本编译。通常,ripgrep 跟踪 Rust 编译器的最新稳定版本。
要构建 ripgrep:
```
$ git clone https://github.com/BurntSushi/ripgrep
$ cd ripgrep
$ cargo build --release
$ ./target/release/rg --version
0.1.3
```
**注意:** 过去,ripgrep 在使用 Rust nightly 编译器时支持 `simd-accel` Cargo 功能。这仅有利于 UTF-16 转码。因为它需要不稳定的功能,这种构建模式容易出错。因此,对其的支持已被移除。如果您想要 UTF-16 转码的 SIMD 优化,则需要请求 [`encoding_rs`](https://github.com/hsivonen/encoding_rs) 项目使用稳定的 API。
最后,可以通过启用 `pcre2` 功能来构建带有可选 PCRE2 支持的 ripgrep:
```
$ cargo build --release --features 'pcre2'
```
启用 PCRE2 功能适用于稳定的 Rust 编译器,并将尝试通过 `pkg-config` 自动查找并链接您系统的 PCRE2 库。如果不存在,ripgrep 将使用您系统的 C 编译器从源代码构建 PCRE2,然后将其静态链接到最终的可执行文件中。即使有可用的 PCRE2 系统库,也可以通过使用 MUSL 目标构建 ripgrep 或设置 `PCRE2_SYS_STATIC=1` 来强制静态链接。
可以在 Linux 上使用 MUSL 目标构建 ripgrep,方法是先在您的系统上安装 MUSL 库(请咨询您友好的社区包管理器)。然后您只需要将 MUSL 支持添加到您的 Rust 工具链并重新构建 ripgrep,这会产生一个完全静态的可执行文件:
```
$ rustup target add x86_64-unknown-linux-musl
$ cargo build --release --target x86_64-unknown-linux-musl
```
按预期应用上面的 `--features` 标志。如果您想使用 MUSL 和 PCRE2 构建静态可执行文件,则需要安装 `musl-gcc`,根据您的 Linux 发行版,它可能与实际的 MUSL 库位于不同的包中。
### 运行测试
ripgrep 的测试相对完善,包括单元测试和集成测试。要运行完整的测试套件,请使用:
```
$ cargo test --all
```
从仓库根目录运行。
### 相关工具
* [delta](https://github.com/dandavison/delta) 是一个支持 `rg --json` 输出格式的语法高亮分页器。所以要让它工作,你只需要 `rg --json pattern | delta`。有关更多详细信息,请参阅 [delta 手册中关于 grep 的部分](https://dandavison.github.io/delta/grep.html)。
### 漏洞报告
如需报告安全漏洞,请[联系 Andrew Gallant](https://blog.burntsushi.net/about/)。
如果您希望发送加密消息,该联系页面包含我的电子邮件地址和 PGP 公钥。
### 翻译
以下是 ripgrep 文档的已知翻译列表。这些是非官方维护的,可能不是最新的。
* [中文](https://github.com/chinanf-boy/ripgrep-zh#%E6%9B%B4%E6%96%B0-)
* [西班牙文](https://github.com/UltiRequiem/traducciones/tree/master/ripgrep)
标签:Awesome, Git集成, grep替代, Rust, SOC Prime, 可视化界面, 开发工具, 性能优化, 搜索引擎, 数据泄露, 文件检索, 检测绕过, 源码分析, 系统管理, 网络安全审计, 网络流量审计, 递归搜索, 通知系统