最快的grep


80

我想知道是否有任何提示可以使您grep尽快完成。我有大量的文本文件,可以以最快的方式进行搜索。我把它们都改成小写,这样我就可以摆脱-i选择了。这样可以使搜索更快。

另外,我发现-Fand-P模式比默认模式更快。如果搜索字符串不是正则表达式(仅是纯文本),则使用前者;如果涉及到正则表达式,则使用后者。

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


1
这总是同一套文件吗?如果您发现自己使用搜索了相同(大)文件集grep,也许是时候寻找一种解决方案来对它们进行正确索引了(“最佳”解决方案取决于这些文件是哪种文件)。
FatalError 2012年

是的,它是同一组文件。您认为像Lucene这样的全文解决方案会提高性能吗?通常,搜索2500个文件(每本文学书)大约需要30/40秒,总单词数约为2.5亿个单词。
pistacchio 2012年

1
"...or maybe make the search parallel in some way?"听到这个消息,我会感到非常兴奋。 grep应该完全能够并行运行,但是我怀疑搜索可能仍然受I / O约束。
Conrad.Dean 2012年

2
您是否尝试过使用ack-grep
meder omuraliev 2012年

Answers:


104

尝试使用GNU parallel,其中包括如何grepGNU parallel一起使用的示例

grep -r通过目录递归浏览。在多核CPU上,GNU parallel通常可以加快速度。

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

每个内核将运行1.5个作业,并为分配1000个参数grep

对于大文件,它可以使用--pipe--block参数将输入分为几个块:

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

您还可以通过SSH(需要避免密码的ssh-agent)在几台不同的计算机上运行它:

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

5
用于--color=always保留grep颜色(在管道中也使用grep时也是如此)
Jim

2
如果find具有-print0谓词(大多数情况),则最好使用find . -type f -print0 | parallel -0 -k …。我的实例man(1) parallel实际上是这样说的。另外,我怀疑globstar如果您shopt -s globstar; parallel -k -j150% -n 1000 -m fgrep -H -n STRING ::: **/*.c
遵循

3
@WilliamPursell它是一个有用的应用cat,如果你想sudo访问bigfile
Jayen

2
为什么每个核心设置1.5个作业?为什么不每个核心有1个工作?
JohnGalt

2
@JohnGalt磁盘I / O通常会停止进程之一。通过启动比核心数量更多的资源,即使所有作业正在等待数据,仍然需要为所有核心做一些事情。调整150%以查看最适合您的系统的情况。
Ole Tange

70

如果要搜索非常大的文件,那么设置区域设置确实可以提供帮助。

GNU grep在C语言环境中的运行速度比使用UTF-8快得多。

export LC_ALL=C

1
令人印象深刻的是,看起来这条直线的速度是2倍。
Fedir RYKHTIK

有人可以解释为什么吗?
罗伯特·E·梅利2014年

5
“简单字节比较与多字节字符比较” <我的老板说...对对对
Robert E Mealey 2014年

7
因此,这并不是完全安全的,特别是在您进行模式匹配(而不只是字符串匹配)或文件内容不是ascii的情况下。在某些情况下仍然值得做,但要谨慎。
罗伯特·E·梅利2014年

@RobertEMealey他说的是“单”而不是“简单”吗?
伊利亚·林恩

12

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]

从自述文件

它建立在Rust的regex引擎之上。Rust的regex引擎使用有限自动机,SIMD和积极的文字优化来使搜索变得非常快。


这非常快!
击败


4

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

我将操作转移到便宜的SSD驱动器(120GB)上。如果您要定期处理大量文件,价格约为100美元,这是一个负担得起的选择。


3

如果您不关心哪个文件包含该字符串,则可能需要将读取grepping分为两个作业,因为生成grep很多次可能会很昂贵-每个小文件一次。

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

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

  2. 许多小的压缩文件(按inode排序)

    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 {}


2

在Sandro的回应基础上,我看了他在此处提供的参考资料并试用了BSD grep与GNU grep。我的快速基准测试结果表明:GNU grep速度更快。

因此,我对原始问题“最快的grep”的建议是:确保您使用的是GNU grep而不是BSD grep(例如,这是MacOS上的默认设置)。


搜索250 MB .sql转储文件时,我在13英寸MacBook Pro上显示的BSD Grep速度比8GB,6核Linode快。6 s vs 25 s
AnthumChris 2015年

2

我个人使用ag(silver searcher)代替grep,它的运行速度更快,您也可以将其与并行和管道块结合使用。

https://github.com/ggreer/the_silver_searcher

更新:我现在使用https://github.com/BurntSushi/ripgrep,它比ag快,具体取决于您的用例。


我发现了一个错误。有时它不会深入到树中,我有grep显示结果但ag没有的情况。我不能牺牲速度的准确性。
username_4567

1
您应该在他们的github帐户上打开一个Issue并进行报告(我可以这样做,但是我无法复制),因为到目前为止我还没有发现任何错误。当然,他们会解决这个问题,是的,您是对的,我完全同意:准确性至上。
Jinxmcg

1

我发现在单个大文件中使用grep进行搜索(尤其是更改模式)的速度更快,是使用split + grep + xargs及其并行标志。例如:

在一个名为my_ids.txt的大文件中有一个要搜索的id文件,bigfile的名称bigfile.txt

使用split将文件拆分为多个部分:

# 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[a-z]), in my example I have 10 million rows in bigfile
split -l 1000000 bigfile.txt
# Produces output files named xa[a-t]

# 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分钟的工作。我敢肯定,效率方面存在某种钟形曲线,显然,超过可用的内核不会给您带来任何好处,但是,这比上面对我的要求的上述任何评论都更好。与使用大多数(linux)本机工具的脚本并行处理相比,这具有更多的好处。


0

cgrep(如果可用)可以比grep快几个数量级。


0

MCE 1.508包括一个支持许多C二进制文件的双块级{file,list}包装器脚本。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 parallel并非如此。我真的希望GNU Parallel在这里工作。此外,mce_grep确实子壳(SH -c /路径/到/ grep)来调用二进制时。

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


您需要提供免责声明,成为该工具的作者。
FractalSpace

0

与原始主题略有不同:googlecodesearch项目中的索引搜索命令行实用程序比grep快得多:https : //github.com/google/codesearch

编译后(需要golang包),您可以使用以下方法索引文件夹:

# index current folder
cindex .

索引将在 ~/.csearchindex

现在您可以搜索:

# search folders previously indexed with cindex
csearch eggs

我仍然通过grep传递结果以获取彩色匹配。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.