官方信息表
| 项目 | 说明 |
|---|---|
| 项目名称 | The Silver Searcher(命令名 ag) |
| 一句话定位 | 类似 ack 的代码搜索工具,主打速度 |
| 代码仓库 | ggreer/the_silver_searcher |
| 实现语言 | C |
| 官方网站 | geoff.greer.fm/ag |
| 开源协议 | Apache-2.0 |
配图

项目背景
The Silver Searcher,命令名是 ag,是一个“类似 ack、专注速度”的代码搜索工具。README 开篇就写道:“A code searching tool similar to ack, with a focus on speed.” 它解决的问题是:当你在一个庞大的代码仓库里想搜某个函数名、某个字符串时,传统的 grep -r 会把所有文件(包括二进制、.min.js、.git 里的东西)都扫一遍,慢得让人抓狂。
它的设计思路是“默认就该懂工程约定”:进入一个目录后,ag 默认遵守 .gitignore、.hgignore,还会跳过隐藏文件和二进制文件,把搜索范围限定在你真正关心的源码上。README 还提到它用 pthreads 做并行搜索、对大文件用内存映射、用 PCRE 或 Boyer-Moore 优化匹配,所以在大型仓库里往往比 grep -r 快一个数量级。你只要敲 ag 关键词,它就把命中的文件、行号、整行内容直接列出来,省去了 grep 那一堆过滤参数。
常用命令行参数包括:ag -g 文件名 类似 find 找文件;ag -i 忽略大小写;ag -l 只列文件名不列内容;ag -A 3 关键词 显示命中行后 3 行上下文;ag --ruby 关键词 只搜 Ruby 文件;ag --cpp 关键词 只搜 C/C++。README 还说明它默认会忽略 .gitignore 里列的东西,如果你确实想搜被忽略的文件,加 --all-types 或显式指定类型即可。
它和 grep 的关键差别在于“默认行为”:grep 默认什么都搜,你得自己加 --exclude-dir=.git、--include='*.c' 之类一堆参数;ag 默认就知道哪些是源码、哪些是构建产物,一行 ag 关键词 就能直接给你干净结果。这也是它从 ack 演进过来的核心价值——把工程约定变成默认行为。
总的来说,ag 是一个“为在大型代码库里快速搜东西而生”的工具:它默认就尊重 .gitignore、并行多核、内存映射、用 PCRE 和 Boyer-Moore 优化,把搜索这件高频小事做得又快又安静。装上之后,你最常做的就是在项目目录里敲 ag 关键词,然后等结果。
作者还写了一系列博客,记录自己如何加 pthreads、逐版本基准测试发现性能回退、用 gprof 和 Valgrind 做 profiling,这些文章都附在 README 里。想了解命令行工具性能优化方法论的读者,值得一读。
在大型代码仓库里,ag 已经成为很多开发者默认的搜索工具:它把“哪些文件该搜、怎么搜得快”这些约定做成了默认行为,让你把注意力集中在要找的内容上,而不是调 grep 参数。
ag 的思路是:它默认尊重你仓库里的 .gitignore 和 .hgignore,自动跳过你不想让它搜的文件;如果你还有额外想排除的文件,往一个 .ignore 文件里加模式就行。README 很接地气地吐槽了一句:“如果源码仓库里有你不想搜的文件,就把它们的模式加到 .ignore 文件里(比如 *.min.js)。”
README 给出的基准很有说服力:在作者约 8GB 的 ~/code 目录里搜 test_blah,ack 花了 110 秒,而 ag 只花了 3.2 秒,快了约 34 倍;两者找到的结果完全一样,而且因为尊重了 ignore 文件,ag 实际只扫了其中 700MB。README 还自豪地补了一句:命令名 ag 比 ack 短了 33%,而且所有按键都在键盘的 home row 上。
在 ag 之前,想在大型代码库里做高效搜索,开发者通常在 grep、ack、git grep 之间折腾:grep 太笨,会扫所有文件;ack 聪明一些但还是慢;git grep 快但只能在 git 仓库里用。ag 想做的是一个“开箱即用、跨平台、默认就尊重工程习惯”的搜索工具——你不需要记住复杂的排除参数,只要在项目目录里敲 ag 关键词,它就自动知道哪些文件是构建产物、哪些是压缩过的第三方库、哪些是版本控制目录,然后只在真正的源码里找。这种“把约定做进工具里”的设计,让它在很长一段时间里成为很多开发者终端里的默认搜索命令。
为什么这么快
README 专门用一节解释了 ag 为什么快,下面逐条翻译。
多线程并行搜索。 ag 用 Pthreads 利用多核 CPU,并行地搜索文件,而不是一个核一个核地排队。
内存映射文件。 它用 mmap() 把文件映射进内存,而不是先读到缓冲区里,减少了一次拷贝。
字面量搜索用 Boyer-Moore。 搜固定字符串时,它用 Boyer-Moore 字符串搜索算法,跳过不可能匹配的位置。
正则用 PCRE JIT。 当用 PCRE(≥8.21)编译时,正则搜索会用到 PCRE 的 JIT 编译器;并且在对每个文件执行同一正则前,先调用 pcre_study() 做优化。
忽略模式用二分查找。 对 ignore 文件里的非正则模式,ag 不是对每个模式都调一次 fnmatch(),而是把它们加载进数组做二分查找,进一步降低了过滤开销。
这一套组合拳的效果,就是 README 给出的那个 34 倍提速:在 8GB 目录里,grep 或 ack 可能把时间花在扫 .git、node_modules、压缩产物上,而 ag 先用 ignore 规则把搜索范围砍到 700MB,再用多核并行、内存映射、Boyer-Moore 和 PCRE JIT 把剩下的文件飞快地过完。它快的不是“某一个技巧”,而是“从过滤到读取到匹配”整条链路都做了针对性优化。
环境要求与部署
README 给出了各平台的包管理器安装方式,以及从源码编译的方法。
方式一:用包管理器安装(推荐)
macOS:
brew install the_silver_searcher
Linux 各发行版:
# Ubuntu >= 13.10 / Debian >= 8
apt-get install silversearcher-ag
# Fedora 22+
dnf install the_silver_searcher
# Arch
pacman -S the_silver_searcher
# openSUSE
zypper install the_silver_searcher
Windows 上,README 给出了几种途径:非官方每日构建在 k-takata 的 win32 仓库;可以用 winget:winget install "The Silver Searcher";或用 Chocolatey:choco install ag;或在 MSYS2 里 pacman -S mingw-w64-{i686,x86_64}-ag。
方式二:从源码编译
README 说明先装依赖(automake、pkg-config、PCRE、LZMA):
# Ubuntu/Debian
apt-get install -y automake pkg-config libpcre3-dev zlib1g-dev liblzma-dev
然后运行构建脚本:
./build.sh
sudo make install
如果下的是 GPG 签名的 Release tarball(在 作者网站),就不需要 automake 和 pkg-config,直接:
./configure
make
make install
对于普通用户,README 强烈建议直接用包管理器安装,因为源码编译需要先装 automake、pkg-config、PCRE、LZMA 一堆开发库,而大多数发行版的仓库里都已经打包好了 ag,一条 apt install 或 brew install 就能用。只有当你需要最新的未发布特性、或者在一个没有包管理器的环境里移植时,才需要走 ./build.sh 源码路线。
使用方法
最基本的用法就是在项目目录里搜一个词:
ag "搜索词"
ag 会自动跳过 .gitignore 里的文件、隐藏文件和二进制文件,递归搜索当前目录,并把匹配的文件名、行号和高亮内容打印出来。你可以像用 grep 一样加正则,比如 ag "def \w+\(" 搜函数定义。
和 grep 相比,ag 的输出默认就是“文件路径 + 行号 + 高亮匹配行”,不需要你额外加 -r、--include、排除二进制这些参数。它默认假设你是在一个工程目录里工作,所以直接帮你把不想看的东西都过滤掉了。这种“约定优于配置”的设计,正是它在开发者社区里流行多年的原因。
README 还给出了编辑器集成方式:在 Vim 里用 ack.vim,在 .vimrc 里加 let g:ackprg = 'ag --vimgrep',就能在 Vim 里直接用 ag 搜索;Emacs 用户可以用 ag.el 或 helm-ag。
这种“命令行好用、编辑器里也能当后端”的设计,让 ag 不只是一个终端命令,而是整个开发流程里的搜索基础设施。你在终端里用它快速定位代码,在编辑器里又通过插件用同样的引擎跳转,搜索行为和结果保持一致,不用在不同工具之间适应不同的排除规则。
在日常使用中,ag 的常见姿势还有很多:加 -l 只列出匹配的文件名而不是整行内容;加 -C 3 在匹配行前后各显示 3 行上下文;加 --html 之类的类型参数只搜指定类型的文件;或者把它的输出接给其他命令做进一步处理。README 强调它现在已经相当稳定,大部分改动是新功能、小修复或性能改进,你可以放心把它放进自己的开发环境长期使用。
举几个真实场景:当你想知道“某个函数名在整个项目里都被谁调用了”,在仓库根目录执行 ag 函数名,几秒钟内就能得到一份按文件分组、带行号和上下文的清单,而且不会被 dist/、node_modules/ 里的重复文件污染;当你想全局替换某个字符串,先 ag 旧字符串 确认影响范围,再决定用不用 sed 批量替换;当你在 Vim 里配好 ag 作为搜索后端,按下 <leader><leader> 就能全项目跳转到任意符号。它的价值不在于某个炫技功能,而在于把“在代码里找东西”这件每天都要做几十遍的事变快、变安静。作者还写了一系列博客,记录自己如何加 pthreads、自己写 scandir()、逐版本基准测试来发现性能回退、用 gprof 和 Valgrind 做 profiling,这些文章都附在 README 里,想了解性能优化方法论的读者可以一读。
在实际的工具链里,ag 常和编辑器、版本控制、其他命令行工具组合使用:你在终端用 ag 快速定位,然后用编辑器打开;它的输出可以被 xargs、awk 进一步处理。虽然现在 ripgrep 等新项目在速度上也很强,但 ag 作为经典的“默认尊重工程约定”的搜索工具,至今仍被大量脚本和配置引用,学习它的用法对理解命令行搜索生态很有帮助。
总的来说,ag 是一个“为在大型代码库里快速搜东西而生”的工具:它默认就尊重 .gitignore、并行多核、内存映射、用 PCRE JIT 和 Boyer-Moore 优化,把搜索这件高频小事做得又快又安静。装上之后,你最常做的就是在项目目录里敲 ag 关键词,然后等结果。
常见问题(FAQ)
问:ag 和 grep、ack 比有什么优势? README 的基准显示它比 ack 快约 34 倍,因为它自动尊重 .gitignore/.hgignore、并行多线程、内存映射文件、用 PCRE JIT 和 Boyer-Moore 优化,不搜无关文件,只扫你真正关心的代码。
问:怎么让 ag 不搜某些文件? README 说明它默认读 .gitignore 和 .hgignore;如果你还有额外想排除的文件,把模式写进一个 .ignore 文件即可,例如 *.min.js。
问:Windows 上怎么装? README 给出:winget winget install "The Silver Searcher"、Chocolatey choco install ag、MSYS2 pacman -S mingw-w64-{i686,x86_64}-ag,以及非官方每日构建。
问:从源码编译需要哪些依赖? README 列出 automake、pkg-config、PCRE、LZMA;Ubuntu/Debian 上 apt-get install -y automake pkg-config libpcre3-dev zlib1g-dev liblzma-dev,然后 ./build.sh && sudo make install。
问:能集成到编辑器里吗? README 说明 Vim 配 ack.vim 加 let g:ackprg = 'ag --vimgrep';Emacs 用 ag.el 或 helm-ag;TextMate 有对应的 AckMate fork。
问:它和 ripgrep、git-grep 是什么关系? README 在“其他你可能喜欢的工具”里列出了 ripgrep、git-grep、fzf 等;ag 是其中经典的一款,这些工具各有侧重,可以按需选用。
问:为什么 ag 不会搜到 .git 目录里的东西? README 说明它会自动忽略 .gitignore 和 .hgignore 里的模式,以及隐藏文件和二进制文件;这正是它比裸 grep -r 快的原因之一——从一开始就不碰那些你不关心的文件。
问:ag 现在还活跃维护吗? README 表示它“quite stable now”,大部分改动是新功能、小 bug 修复或性能改进;如果你熟悉 C 并想参与改进,作者甚至在 README 里邀请你和他结对编程。
问:我已经在用 grep,有必要换 ag 吗? README 的对比很直接:grep 不识别 .gitignore,会扫所有文件包括你不想看的二进制和构建产物;ag 默认就尊重工程里的 ignore 文件、并行多核、只搜源码。如果你经常在大型仓库里搜代码,换过去会有非常明显的提速;如果你只是偶尔搜单个小文件,那 grep 也够用。
问:ag 能搜压缩文件或二进制内容吗? README 的设计取向是“只搜源码”:它会自动跳过二进制文件和隐藏文件,专注于文本源码的快速检索。它不是为在二进制里抠字符串设计的,那种场景请用 strings 加 grep,或者专门的二进制分析工具。
跳转链接
- 官方代码仓库:ggreer/the_silver_searcher
- 作者网站:geoff.greer.fm/ag
- 性能对比图:geoff.greer.fm/ag/speed
- Windows 非官方构建:k-takata/the_silver_searcher-win32
- Vim 集成:mileszs/ack.vim
- Emacs 集成:Wilfred/ag.el
- 同类工具:BurntSushi/ripgrep