2011-05-14 55 views
16

任何人都可以解釋如何在Ruby中使用正則表達式來僅返回字符串的匹配。在與正則表達式匹配的文本文件中查找行

例如,如果代碼.txt文件,在其一系列的名字寫着:

John Smith 
James Jones 
David Brown 
Tom Davidson 
etc etc 

..和相匹配的單詞鍵入作爲「翁」,它會再只是返回'約翰史密斯',但沒有其他的名字。

回答

14

也許我沒有完全理解問題,但你可以這樣做:

File.readlines("path/to/file.txt").select { |line| line =~ /ohn/ } 

讓所有符合條件的行的數組。

9
query = 'ohn' 
names = File.readlines('names.txt') 
matches = names.select { |name| name[/#{query}/i] } 
#=> ["John Smith"] 

如果您希望查詢區分大小寫,請刪除正則表達式末尾的i

+0

這是完美的一個列表,謝謝指點先生! – Jbod 2011-05-14 15:49:10

21

以下是一些不同的方法來獲取你要去的地方。

請注意首先我使用了一種更習慣的方式來編寫從文件中讀取行的代碼。 Ruby的IO和文件庫使得打開,讀取和關閉文件變得非常簡單,並且它是一個非常整潔的包。

File.each_line('file.txt') do |li| 
    puts li if (li['ohn']) 
end 

在該行的任何位置查找'ohn',但不打擾正則表達式。

File.each_line('file.txt') do |li| 
    puts li if (li[/ohn/]) 
end 

查找相同的字符串,只有它使用正則表達式才能到達那裏。在功能上它與第一個例子相同。

File.each_line('file.txt') do |li| 
    puts li if (li[/ohn\b/]) 
end 

這是一種尋找以'ohn'結尾的名字的更智能的方法。它使用正則表達式,但也指定該模式必須發生在單詞的末尾。 \b的意思是「單詞邊界」。

此外,讀取文件時,始終考慮讀取的文件是否會超過可用於應用程序的RAM很重要。將整個文件一次讀入內存很容易,然後通過RAM進行處理,但是如果超過可用的物理RAM,則可能會損壞或終止應用程序或機器。


你知道如果其他的答案中顯示的代碼實際上是在加載整個文件到內存或者以某種方式從readlines方法的功能流的選擇功能優化?

IO#readlines文檔:

讀取通過名稱指定爲單獨線路的整個文件,並且在陣列返回的那些行。行由sep分隔。

一個額外的考慮因素是大容量讀取期間的內存分配。即使你有足夠的內存,你也可能會遇到語言在讀入數據時窒息,發現它沒有爲變量分配足夠的內存,並且因爲抓取的內存更多而暫停。該循環重複,直到整個文件被加載。

多年前,當我將一個非常大的數據文件加載到惠普最大的迷你機上的Perl應用程序中時,我變得非常敏感。該應用程序會暫停幾秒鐘,我不知道爲什麼。我掉進調試器,找不到問題。最後,通過使用舊式打印語句來追蹤跑步,我將暫停狀態隔離爲文件「slurp」。我有足夠的內存和足夠的處理能力,但Perl並沒有分配足夠的內存。我開始逐行閱讀,應用程序通過其處理。 Ruby和Perl一樣,具有良好的I/O,並且可以在逐行讀取時快速讀取大文件。我從來沒有發現啜泣文本文件的好理由,除非有可能讓我想要分佈在多行上的內容,但這不是一種常見現象。

+1

+1考慮到記憶。你知道其他答案所顯示的代碼實際上是將整個文件加載到RAM中,還是通過從'readlines'函數到'select'函數的流式傳輸進行優化? – 2011-05-15 06:10:58

+0

+1不能將整個文件讀入內存。 – 2011-05-15 19:42:14

+1

@JasonM,任何建議使用'readlines'的答案都會將整個文件加載到內存中。它是一個數組,但它在內存中。 – 2012-09-13 18:52:20

1

老問題,但Array#grep也可以用來搜索字符串

File.readlines("names.txt").grep /#{query}/i