如何在 fgrep/Ag 中更快地进行此搜索?

Léo*_* 준영 6 grep time parallelism ag

我正在考虑使搜索更快和/或更好的方法,主要使用fgrepor agand不区分大小写地搜索单词at$HOME并将匹配列表重定向到的代码vim

find -L $HOME -xtype f -name "*.tex" \
   -exec fgrep -l -i "and" {} + 2>/dev/null | vim -R -
Run Code Online (Sandbox Code Playgroud)

这是更快,有ag因为并行的和ack

find -L $HOME -xtype f -name "*.tex" \
   -exec ag -l -i "and" {} + 2>/dev/null | vim -R -
Run Code Online (Sandbox Code Playgroud)

统计数据

小群的平均统计信息fgrep,并ag通过time

        fgrep   ag     terdon1  terdon2  terdon3  muru 
user    0.41s   0.32s  0.14s    0.22s    0.18s    0.12s
sys     0.46s   0.44s  0.26s    0.28s    0.30s    0.32s
Run Code Online (Sandbox Code Playgroud)

情况terdon1terdon3可以一样快。我对这两个波动很大。一些sys时间排名(不是最好的标准!)

  1. terdon1
  2. terdon2
  3. 特顿3
  4. 穆鲁
  5. fgrep

缩写

  • terdon1 = terdon-many-find-grep
  • terdon2 = terdon-many-find-fgrep
  • terdon3 = terdon-many-find-ag(没有 F 因为不存在于ag

其他代码

muru 在评论中的提议

grep -RFli "and" "$HOME" --include="*.tex" | vim -R -
Run Code Online (Sandbox Code Playgroud)

操作系统:Debian 8.5
硬件:Asus Zenbook UX303UA

RJH*_*ter 6

由于您正在使用ackSilver Searcher ( ag),因此您似乎可以使用其他工具。

这个领域的一个新工具是 ripgrep ( rg)。它旨在快速查找要搜索的文件(如ag)和快速搜索文件本身(如普通的旧 GNU grep)。

对于您的问题中的示例,您可以使用以下内容:

rg --files-with-matches --glob "*.tex" "and" "$HOME"
Run Code Online (Sandbox Code Playgroud)

ripgrep 的作者发布了对不同搜索工具如何工作的详细分析,以及基准比较。

其中一项基准测试linux-literal-casei与您描述的任务有些相似。它在许多嵌套目录(Linux 代码库)中搜索大量文件,搜索不区分大小写的字符串文字。

在该基准测试中,rg使用白名单时速度最快(例如您的“*.tex”示例)。该ucg工具在该基准测试中也表现良好。

rg (ignore)         0.345 +/- 0.073 (lines: 370)
rg (ignore) (mmap)  1.612 +/- 0.011 (lines: 370)
ag (ignore) (mmap)  1.609 +/- 0.015 (lines: 370)
pt (ignore)        17.204 +/- 0.126 (lines: 370)
sift (ignore)       0.805 +/- 0.005 (lines: 370)
git grep (ignore)   0.343 +/- 0.007 (lines: 370)
rg (whitelist)      0.222 +/- 0.021 (lines: 370)+
ucg (whitelist)     0.217 +/- 0.006 (lines: 370)* 
Run Code Online (Sandbox Code Playgroud)

* - 最佳平均时间。+ - 最佳采样时间。

作者ack从基准测试中排除,因为它比其他基准慢得多。

  • 您可以在此处下载自包含的二进制文件:https://github.com/BurntSushi/ripgrep/releases --- Debian 软件包正在开发中。Ripgrep 应该是最早打包的 Rust 程序之一! (2认同)

ter*_*don 4

find您可以通过并行运行多个调用来使其更快一点。例如,首先获取所有顶级目录并运行 N 个查找调用,每个目录一个。如果您在子 shell 中运行,您可以收集输出并将其传递给 vim 或其他任何东西:

shopt -s dotglob ## So the glob also finds hidden dirs
( for dir in $HOME/*/; do 
    find -L "$dir" -xtype f -name "*.tex" -exec grep -Fli and {} + & 
  done
) | vim -R -
Run Code Online (Sandbox Code Playgroud)

或者,确保只有在所有查找完成后才开始获取输出:

( for dir in $HOME/*/; do 
    find -L "$dir" -xtype f -name "*.tex" -exec grep -Fli and {} + & 
  done; wait
) | vim -R -
Run Code Online (Sandbox Code Playgroud)

我进行了一些测试,上面的速度确实比单一的稍快一些find。平均而言,运行 10 次以上,单个find调用工具花费了 0.898 秒,上面的子 shell 为每个目录运行一次查找花费了 0.628 秒。

我假设详细信息始终取决于您有多少个目录$HOME、其中有多少个目录可以包含.tex文件以及有多少个目录可能匹配,因此您的情况可能会有所不同。

  • 请注意,ripgrep 会自动为您并行化目录遍历。 (2认同)