2009-12-22 57 views
1

你可以建议我任何CPAN模块在大型分类文件上搜索吗?如何在Perl中搜索大型的排序文件?

该文件是一个约1500万到2000万行的结构化数据,但我只需要找到大约25,000个匹配项,所以我不想将整个文件加载到散列中。

谢谢。

+3

你可以使用'while <$fh>'吗? – 2009-12-22 01:34:01

+4

您打算如何处理匹配的条目?如果你只是需要它们在一个较小的文件:grep foo big.file> smaller.file – toolic 2009-12-22 01:44:06

+0

为什么你的文件排序是否重要?你是否试图利用文件的分类来加速你的搜索?您可以使用二进制搜索。 'seek()'是用来在文件中跳转的函数。 – daotoad 2009-12-22 04:31:42

回答

5

扫描整个文件可能是最快的方法。您也可以尝试File::Sorted,它将对给定记录进行二分法搜索。在2500万行文件中查找一条记录应该要求每个记录约15-20个搜索。这意味着要查找25,000条记录,您只需要约500万个查询/比较,而对于每行25,000,000个查询,则需要天真。

磁盘IO就是它,你可能想先尝试简单的方法,但File :: Sorted是理论上的胜利。

+0

您的File :: Sorted正在使用当前未安装在我们的生产环境中的Moose。我在CPAN上找到了File :: SortedSeek,它似乎在执行二进制搜索 - 是否达到同样的目的? 而我对速度性能和内存占用情况的测试看起来不错。 – est 2009-12-23 04:09:06

6

Perl非常适合这样做,而不需要外部模块(来自CPAN或其他地方)。

一些代码:

while (<STDIN>) { 
    if (/regular expression/) { 
     process each matched line 
    } 
} 

你需要拿出自己regular expression指定要在你的文件,以配合其行。一旦匹配,您需要自己的代码来处理每条匹配的行。

将上面的代码放在一个脚本文件中,并将它与您的文件重定向到stdin一起运行。

+0

我想避免在2500万行和25000行文件上使用嵌套while循环,因为它是线性的并且需要很长时间。 – est 2009-12-23 04:47:59

2

当您使用while (<$filehandle>)处理输入文件时,它每次只需要一行文件(对于循环的每次迭代),因此您不必担心会堵塞内存。与for循环不同,循环将整个文件分散到内存中。使用正则表达式或任何其他来找到你要找的东西,并把它放在一个变量/数组/散列或写出来一个新的文件。

3

你不想搜索文件,所以尽你所能避免它。我们不知道很多关于你的问题,但这里有一些技巧我在前面的问题中,所有这些尝试做工作的时间提前:

  • 将文件分解成一个数据库。甚至可以是SQLite。
  • 根据您要搜索的数据对文件进行预先索引。
  • 缓存先前搜索的结果。
  • 自动提前运行常用搜索。

所有这些交易存储空间,以加快速度。我将设置一些作为隔夜工作的这些工作,以便他们在工作时准备就绪。

你提到你有结构化的数据,但不要再说了。每条线都是完整的记录吗?这个文件多久改变一次?

+0

目前我对二进制搜索的性能非常满意(如jrockway所建议的),而不是将整个2000万行输入散列。 大文件每季度更改一次,所以我会将其移至使用SQLite或DBM。 – est 2009-12-23 04:39:55

3

听起来像你真的想要一个数据库。考虑SQLite,使用Perl的DBI和DBD :: SQLite模块。