我正在寻找一种比 grep 更快的工具,也许是多线程 grep,或者类似的东西...我一直在看一堆索引器,但我并不认为我需要一个索引......
我有大约 1 亿个文本文件,我需要在其中 grep 查找精确的字符串匹配,找到字符串匹配后,我需要找到匹配项的文件名。
ie: grep -r 'exact match' > filepaths.log
它的数据量大约为 4TB,我 6 天前开始了我的第一次搜索,而 grep 仍在运行。我还有十几个搜索要做,我等不及 2 个月来检索所有这些文件名 =]
我已经审查了以下内容,但是,我认为我不需要这些索引器附带的所有花哨功能,我只需要发生匹配的文件名......
- 查询
- 梗类犬
- Lucene
- 沙比安
- 畏缩
- 狮身人面像
在花了几个小时阅读有关所有这些引擎的文章后,我的头开始旋转,我希望我有一个多线程的 grep lol,任何想法和/或建议都将非常感谢!
PS:我运行的是 CentOS 6.5
编辑:搜索多线程 grep 返回几个项目,我的问题是,多线程 grep 是否是我正在做的事情的最佳选择?
EDIT2:经过一些调整后,这就是我想出的办法,它比常规的 grep 快得多,但我仍然希望它更快...我正在观察我的磁盘 io 等待,但它还没有建立起来,我可能会做更多的调整,并且仍然对任何建议感兴趣 =]
find . -type f -print0 | xargs -0 -n10 -P4 grep -m 1 -H -l 'search string'
答案1
grep
受 I/O 限制,这意味着其速度取决于其读取所搜索文件的速度。并行的多个搜索可能会相互竞争磁盘 I/O,因此您可能看不到太大的加速。
如果您只需要匹配文件名,而不是文件中找到的实际匹配项,那么您应该使用标志运行 grep -l
。此标志使 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.*
它用于find
查找文件,将文件名列表分成一千万个组,并对每个组并行运行 grep。最后将 grep 的输出全部连接在一起。这应该适用于具有典型名称的文件,但对于名称中包含换行符的文件,它会失败。
另一种方法是使用 xargs。首先,您必须编写一个在后台运行 grep 的简单 shell 脚本:
#!/bin/bash
grep -l 'search text' "$@" >> grep.$$.out &
这将对脚本中指定的文件列表运行 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
在这种情况下,xargs
将把文件名打包成组,并为每个组运行一次脚本。脚本将为每个组运行一次 grep 实例。一旦所有 grep 实例都完成,您就可以合并它们的输出。不幸的是,我想不出一个聪明的方法来自动等待 grep 实例完成,所以你可能不得不手动完成。
答案2
听起来你需要一个脚本或小程序来运行多个 grep 实例(即 8 x grep 可以在具有 4 核/8 线程的现代 i7 上并行运行)并连接或合并输出,而不是需要一个更快的 grep。
如何制作这样的脚本是另一个问题,但这就是我解决你的问题的方式。