如何在 fgrep/Ag 中加快搜索速度?

如何在 fgrep/Ag 中加快搜索速度?

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

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

由于ag并行性和ack

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

统计数据

小组平均统计fgrep数据agtime

        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

terdon1terdon3可以相等快。我对这两个人的态度波动很大。一些按时间排名sys(不是最佳标准!)

  1. 特登1
  2. 特登2
  3. 特登3
  4. 穆鲁
  5. 股份公司
  6. 命令行工具

缩写

  • 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 -

操作系统:Debian 8.5
硬件:华硕 Zenbook UX303UA

答案1

由于您正在使用ackThe Silver Searcher ( ag),看来您可以使用其他工具。

这个领域的一个新工具是 ripgrep ( rg)。它的设计速度很快发现要搜索的文件(如ag)并且速度也很快寻找文件本身(就像普通的旧 GNU 一样grep)。

对于您问题中的示例,您可以这样使用它:

rg --files-with-matches --glob "*.tex" "and" "$HOME"

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)* 

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

作者将其排除ack在基准测试之外,因为它比其他测试慢得多。

答案2

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 -

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

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

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

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

相关内容