由于没有其他人回答,我将用我的简单想法开始讨论,希望有聪明的人能够进一步帮助。
首先,这可以很容易地并行化,只需将100万个文件分配到多台服务器上,例如,如果您有4台服务器,则前250,000个文件可以独立于其余文件进行搜索。
然后,每个服务器都可以运行类似于以下内容的代码,假设您的文档以“.txt”结尾:
#!/bin/bash
find . -name "*.txt" | while IFS= read a
do
grep -l banana "$a" | while IFS= read b
do
grep -l motorboat "$b" | while IFS= read c
do
grep -l "the white fox" "$c"
done
done
done
通过在常见单词之前搜索罕见单词,可以提高性能。
此外,您可以使用awk并传入所有3个搜索模式,并在找到它们全部后立即退出,而不是继续处理直到文件结尾。
当然,如果您要执行多个重复查询,则值得花费更多时间将文件加载到高效的结构(例如哈希)中。因此,如果您的输入文件包含单词“摩托艇”,则哈希表中将有一个条目,并且仅通过测试哈希表中是否存在该单词即可快速测试文件是否包含该单词。这样可以修剪需要进入上述方法的文件,并大大提高性能。
因此,以下代码将解析所有“.txt”文件,并记录每个单词在哪些文件中。因此,当需要进行搜索时,您可以简单地传递搜索术语并查找包含单词(不一定相邻)的文件,并将该文件列表传递给上面的脚本:
use strict;
use warnings;
my %words;
my @files=<*.txt>;
foreach my $file (@files){
print "Loading: $file\n";
open my $fh, '<', $file or die "Could not open $file";
while (my $line = <$fh>) {
chomp $line;
foreach my $str (split /\s+/, $line) {
$words{$str}{$file}=1;
}
}
close($fh);
}
foreach my $str1 (keys %words) {
print "Word: \"$str1\" is in : ";
foreach my $str2 (keys $words{$str1}) {
print "$str2 ";
}
print "\n";
}
我创建的小测试文件的输出如下:
./go
Loading: a.txt
Loading: b.txt
Loading: c.txt
Loading: d.txt
Word: "the" is in : c.txt d.txt
Word: "motorboat" is in : b.txt d.txt
Word: "white" is in : c.txt d.txt
Word: "banana" is in : c.txt d.txt a.txt
Word: "fox" is in : c.txt d.txt