最快可能的grep

我想知道是否有任何提示尽可能快地使grep 。 我有一个相当大的文本文件的基础,以尽可能快的方式进行search。 我已经把它们全写成小写,这样我就可以摆脱-i选项。 这使得search速度更快。

另外,我发现-F-P模式比默认模式快。 当searchstring不是正则expression式(只是纯文本)时使用前者,如果涉及正则expression式则使用后者。

有没有人有加快grep经验? 也许用一些特殊的标志(我在Linux CentOS上)从头开始编译它,以某种方式组织文件,或者以某种方式使search平行?

尝试与GNU并行 ,其中包括如何使用它与grep一个例子 :

grep -r通过目录recursion地greps。 在多核CPU上,GNU parallel通常可以加快速度。

 find . -type f | parallel -k -j150% -n 1000 -m grep -H -n STRING {} 

这将运行1.5每个核心作业,并给1000个参数grep

对于大文件,可以用--pipe--block参数将input分成几个块:

  parallel --pipe --block 2M grep foo < bigfile 

你也可以通过SSH在不同的机器上运行它(ssh-agent需要避免密码):

 parallel --pipe --sshlogin server.example.com,server2.example.net grep foo < bigfile 

如果你正在search非常大的文件,那么设置你的语言环境真的有帮助。

在C语言环境中,GNU grep比UTF-8要快得多。

 export LC_ALL=C 

Ripgrep声称现在是最快的。

https://github.com/BurntSushi/ripgrep

还包括默认的并行性

  -j, --threads ARG The number of threads to use. Defaults to the number of logical CPUs (capped at 6). [default: 0] 

从README

它build立在Rust的正则expression式引擎之上。 Rust的正则expression式引擎使用有限自动机,SIMD和激进的文字优化来快速search。

不是严格的代码改进,而是在运行2百万个文件上的grep后发现有帮助。

我把这个操作转移到了一个便宜的SSD硬盘上(120GB)。 如果你经常处理大量的文件,大约100美元,这是一个负担得起的select。

在Sandro的回应的基础上,我查看了他在这里提供的参考资料,并使用了BSD grep和GNU grep。 我的快速基准testing结果显示:GNU grep速度更快。

所以我build议原始问题“最快可能的grep”:确保你使用的是GNU grep而不是BSD grep(这是MacOS默认的例子)。

如果你不关心哪些文件包含string,你可能希望将阅读grepping分离成两个作业,因为多次产生grep可能代价高昂 – 每个小文件一次。

  1. 如果你有一个非常大的文件:

    parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>

  2. 许多小型压缩文件(按inodesorting)

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>

我通常用lz4压缩我的文件以获得最大的吞吐量。

  1. 如果你只想匹配的文件名:

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}

我个人使用ag(silver searcher)而不是grep,速度更快,也可以将它与平行和pipe道块结合使用。

https://github.com/ggreer/the_silver_searcher

更新:我现在使用https://github.com/BurntSushi/ripgrep ,这比根据你的用例更快。

我发现使用grep在单个大文件中search(特别是对于更改模式)更快的一件事是使用split + grep + xargs并行标志。 例如:

在一个名为my_ids.txt的大文件中find要search的id文件bigfile bigfile.txt的名称

使用拆分将文件拆分成部分:

 # Use split to split the file into x number of files, consider your big file # size and try to stay under 26 split files to keep the filenames # easy from split (xa[az]), in my example I have 10 million rows in bigfile split -l 1000000 bigfile.txt # Produces output files named xa[at] # Now use split files + xargs to iterate and launch parallel greps with output for id in $(cat my_ids.txt) ; do ls xa* | xargs -n 1 -P 20 grep $id >> matches.txt ; done # Here you can tune your parallel greps with -P, in my case I am being greedy # Also be aware that there's no point in allocating more greps than x files 

在我的情况下,这会把一个17小时的工作切成1小时20分钟的工作。 我确信这里有一些关于效率的钟形曲线,显然,通过可用的内核对你没有任何好处,但是对于我上面提到的要求,这是一个比上述任何一个更好的解决scheme。 与使用大多数(linux)本机工具的脚本相比,这有一个额外的好处。

cgrep,如果可用的话,可以比grep快好几个数量级。

MCE 1.508包含一个支持许多C二进制文件的双块级{文件,列表}包装器脚本; agrep,grep,egrep,fgrep和tre-agrep。

https://metacpan.org/source/MARIOROY/MCE-1.509/bin/mce_grep

https://metacpan.org/release/MCE

当需要-i快速运行时,不需要转换为小写。 只需将–lang = C传递给mce_grep。

输出顺序被保存。 -n和-b输出也是正确的。 不幸的是,这个页面上提到的GNU并行并不是这种情况。 我真的希望GNU Parallel在这里工作。 另外,在调用二进制文件时,mce_grep 不是子shell(sh -c / path / to / grep)。

另一个替代scheme是MCE附带的MCE :: Grep模块。

与原始主题略有偏差:来自googlecodesearch项目的索引search命令行实用程序比grep快: https : //github.com/google/codesearch :

一旦你编译它(需要golang包),你可以索引一个文件夹:

 # index current folder cindex . 

该索引将在~/.csearchindex下创build

现在你可以search:

 # search folders previously indexed with cindex csearch eggs 

我仍然通过greppipe道结果来获得彩色匹配。