有什么比 grep 更快的吗?

Jef*_*rts 8 search grep search-engines file-search search-indexing

我正在寻找一种比 grep 更快的工具,也许是多线程 grep 或类似的东西......我一直在寻找一堆索引器,但我并没有因为我需要一个索引而出售......

我有大约 1 亿个文本文件,我需要对精确的字符串匹配进行 grep,在找到字符串匹配时,我需要找到匹配的文件名。

ie: grep -r 'exact match' > filepaths.log
Run Code Online (Sandbox Code Playgroud)

它大约有 4TB 的数据,我在 6 天前开始了我的第一次搜索,grep 仍在运行。我还有十几个搜索要进行,我等不及 2 个月才能检索所有这些文件名 =]

我已经审查了以下内容,但是,我认为我不需要这些索引器附带的所有花里胡哨,我只需要匹配发生的文件名......

  • 搜索
  • 琉森
  • 夏平
  • 畏缩
  • 狮身人面像

在花了几个小时阅读所有这些引擎之后,我的头在旋转,我希望我只有一个多线程 grep 哈哈,非常感谢任何想法和/或建议!

PS:我运行的是 CentOS 6.5

编辑:搜索多线程 grep 会返回几个项目,我的问题是,多线程 grep 是我正在做的事情的最佳选择吗?

EDIT2:经过一些调整后,这就是我想出的,它比常规的 grep 运行得快得多,但我仍然希望它更快……我正在看着我的磁盘 io 等待,它尚未建立,我可能会做更多的调整,并且仍然对任何建议感兴趣 =]

find . -type f -print0 | xargs -0 -n10 -P4 grep -m 1 -H -l 'search string'
Run Code Online (Sandbox Code Playgroud)

Ken*_*ter 11

grep受 I/O 限制,这意味着它的速度取决于它读取正在搜索的文件的速度。多个并行搜索可能会相互竞争磁盘 I/O,因此您可能看不到多少加速。

如果您只需要匹配的文件名,而不是在文件中找到的实际匹配项,那么您应该使用该-l标志运行 grep 。此标志导致 grep 只打印匹配的文件名,而不打印匹配的行。这里的价值在于它允许 grep 在找到匹配项后停止搜索文件,因此它可以减少 grep 必须执行的工作量。

如果您正在搜索固定字符串而不是正则表达式,那么您可以尝试使用fgrep而不是grep. fgrep 是 grep 的一个变种,它搜索固定字符串,搜索固定字符串比运行正则表达式搜索更快。您可能会也可能不会看到任何改进,因为 grep 的现代版本可能足够聪明,可以优化固定字符串搜索。

如果您想尝试并行运行多个搜索,您可以使用 shell 实用程序来完成。一种方法是构建一个文件名列表,将其拆分为多个部分,然后为每个列表单独运行 grep:

find /path/to/files -type f -print | split -l 10000000 list.
for file in list.*; do
    grep -f ${file} -l 'some text' > ${file}.out &
done
wait
cat $*.out > filepaths.log
rm list.*
Run Code Online (Sandbox Code Playgroud)

这用于find查找文件,将文件名列表分成千万个组,并为每个组并行运行 grep。grep 的输出最后都连接在一起。这应该适用于具有典型名称的文件,但对于名称中包含换行符的文件,它会失败。

另一种方法使用 xargs。首先,您必须编写一个在后台运行 grep 的简单 shell 脚本:

#!/bin/bash
grep -l 'search text' "$@" >> grep.$$.out &
Run Code Online (Sandbox Code Playgroud)

这将在指定为脚本参数的文件列表上运行 grep,将结果写入以进程的 PID 命名的文件。grep 进程在后台运行。

然后你会像这样运行脚本:

find /path/to/files -type f -print0 | xargs -0 -r /my/grep/script
[ wait for those to finish ]
cat grep.*.out > filepaths.log
rm grep.*.out
Run Code Online (Sandbox Code Playgroud)

在这种情况下,xargs将文件名捆绑到组中,并为每个组运行一次​​脚本。该脚本将为每个组运行一次​​ grep 实例。完成所有 grep 实例后,您可以组合它们的输出。不幸的是,我想不出一种聪明的方法来自动等待 grep 实例在此处完成,因此您可能必须手动执行此操作。