2009-12-22 62 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模塊。