巧用这几种文本检索工具,节省 80% 的时间!
说到文本搜索工具,大家一定会想到 grep, 它是 Linux 最有用并最常用的工具之一。grep 在我们日常的学习和工作中是必不可少的,但是,当我们需要在一个比较大的工程项目中搜索某个关键词时,grep 的效率是比较低的。
对于所有的检索工具来说,最重要的步骤永远是找出要搜索的内容。而 grep 这个工具就比较质朴,它只是在我们指定路径的所有文件上搜索内容,针对 grep 这种情况,ack 就应运而生了。与 grep 不同,ack 默认情况下不会搜索所有内容,而是尝试一种更加智能的方式来搜索。我们现在所用的大部分检索工具都是从这两个工具中派生出来的,比如 sift 就是由 grep 派生;ag、ucg 和 pt 由 ack 派生;而 ripgrep 混合了两大派系,它有点像 grep 擅长用来搜索大文件,又提供了像 ack 一样的智能搜索。本文给大家介绍 grep、ag 和 rg 三款工具对比。
1. 安装方式
· grep
优麒麟各版本操作系统预装了 grep 工具,不需要额外安装。
· ripgrep
deb 包安装:
· silversearcher-ag
2. 使用方法对比
以上三款工具使用的命令方式存在比较大的差别,但是在检索中文字符串时,默认都只支持 UTF-8 格式的文件。
这里就不列举选项参数了,如有需要可通过 [命令] --help 查看。
· grep
支持正则表达式;功能多样;可以更加精确、灵活地检索出单词;检索范围为指定目录的所有类型的文件;不支持转换编码格式。
· silversearcher-ag
支持正则表达式;检索时会自动忽略 .gitignore 文件和隐藏文件以加快检索速度;默认当前工作目录;默认递归检索;默认显示检索字符串的位置;文件类型如果省略,ag 会检索它支持的所有文件类型,并且 ag 不支持转换编码格式。
· ripgrep
默认选项与 ag 类似。**但是 rg 有 -E 选项可以指定其他编码格式,ag 和 grep 都没有此功能。**在检索中文内容时这个功能很有用,但是用了-E 选项转换到其他编码格式之后,将不支持原先的默认格式,使用时需做出取舍。
使用方法上,grep 具有更好的灵活性,而 rg 和 ag 则更加地智能。它使用简单,可以帮助用户处理掉了一些本来需要用户自己处理的情况,不用记那么多繁杂的命令行参数,但是也有人认为 rg 和 ag 这种做法限制了其适用性。
3. 原理解析
· grep
使用了 Boyer-Moore 字符串检索算法。对输入进行优化,具体方法为使用系统调用,以避免数据拷贝带来的开销,以及避免了对输入进行分行,直接将文本放在了 Buffer 中进行处理,在找到了匹配的字符串之后,再去查找里面有没有换行符,因为查找换行符代价太大,需要逐字符查找。
· ag
ag 使用 pthreads 来利用多核并行搜索文件。文件使用内存映射的方式,而不是读入缓冲区。使用了 Boyer-Moore 字符串检索算法,正则表达式搜索使用了 PCRE 的 JIT 编译器( PCRE 版本大于 8.21 )。
· rg
基于 Rust 的 regex 引擎实现。Rust 的 regex 引擎使用 SIMD 和大量的文本优化,使得搜索速度非常快,还通过将 UTF-8 解码直接构建到引擎中,在完全支持 Unicode 的情况下保持性能。它支持使用内存映射或中间缓冲区增量搜索,前者适用于单个文件,后者适用于大型目录,并且会自动选择最佳搜索策略。
4. 性能对比分析
关于性能方面的对比,没有比实际操作更有说服力的了。同时为了保证检索量足够大,性能差异足够明显,下面我将在一份大型程序源码中(源码行数千万数量级),分别用三个命令搜索同一关键字,并显示其搜索时间(测试环境为 8 核 16GB )。每个工具的具体运行参数如下:
· grep
为保证单一变量,grep 参数设置为 Hrni ,与 ag 和 rg 的默认选项保持一致。
· silversearcher-ag
· ripgrep
由此可见,单论检索速度,ripgrep > silversearcher-ag > grep,且 ripgrep 的性能远超其他两个工具,同时这也证明了在这三款工具中 grep 的性能最低。ag 和 rg 之所以检索速度这么快,除了默认忽略一些文件类型之外,另一个很重要的原因在于它们都采用了多线程的方式,充分利用了多个 CPU 内核的性能。
5. END
从上文分析可以得知,rg 和 ag 无论是在使用上还是性能上,都要优于 grep 。其中, rg 无疑是三个工具当中最好的,大型项目中使用 rg 一定能事半功倍。当然,也不是说 grep 就完全没有用了,在一些特定的场景下,比如我们需要搜索所有文件,包括隐藏文件,那 grep 就可以大展拳脚了。大部分检索场景还是更看重速度,此时最好使用 rg 或 ag 。
评论