2013-07-03 138 views
1

有沒有辦法在Ruby中執行以下Perl結構?Ruby:逐行匹配範圍

while(my $line = $file->each_line()) { 
    if($line =~ /first_line/ .. /end_line_I_care_about/) { 
    do_something; 
    # this will do something on a line per line basis on the range of the match 
    } 
} 

在紅寶石會讀這樣的:

file.each_line do |line| 
    if line.match(/first_line/) .. line.match(/end_line_I_care_about/) 
    do_something; 
    # this will only do it based on the first match not the range. 
    end 
end 

整個文件讀入內存是不是一種選擇,我不知道有多大範圍的大塊。

編輯:

感謝您的答案,我得到了答案,其中基本相同的代碼,我在首位。我遇到的問題是「它可以測試正確的操作數,並在相同的評估中變成錯誤(如在awk中),但它仍然會返回一次。」

「如果你不希望它來測試右操作數,直到下一個評估,如SED,只是用三個點(」 ...「),而不是兩個。在所有其他方面,」 ... 「的行爲就像」..「一樣。」

我標記正確答案爲指出我看到一個「..」可以在同一個關閉調用它製成。

僅供參考我使用的代碼是:

file.each_line do |line| 
    if line.match(/first_line/) ... line.match(/end_line_I_care_about/) 
    do_something; 
    end 
end 

回答

1

我不是對Perl代碼的確切語義清透,假設你想要完全一樣的。 Ruby確實有一些外觀和工作方式類似,或者可能是相同的:作爲條件的Range作爲切換。你給出的代碼工作完全按照我想象你打算。

有幾個注意事項,但是:

  1. 你到達終點條件後,也行會繼續被讀取,直到到達文件的末尾。如果您希望結束條件接近大文件的開頭,這可能是性能考慮因素。

  2. 可以多次觸發啓動條件,重新打開「開關」,執行do_something並再次測試結束條件。這可能是罰款,如果你的條件是不夠具體,或者如果你想要的行爲,但它的東西要注意的。

  3. 的結束條件可以在同一時間啓動條件被稱爲給你真正的只是一個行調用。

這裏有一個選擇:

started = false 

file.each_line do |line| 
    started = true if line =~ /first_line_condition/ 
    next unless started 
    do_something() 
    break if line =~ /last_line_condition/ 
end 

該代碼讀取文件中的每一行,直至達到啓動條件。然後它執行任何你喜歡的處理,直到你到達一個符合你的結束條件的行,在這一點上,它突破循環,不再從文件中讀取更多行。

0

該解決方案是最接近您的需求。它幾乎看起來像Perl,但是這個有效的Ruby(儘管觸發器操作符有點沮喪)。 文件逐行讀取,未完全加載到內存中。

File.open("my_file.txt", "r").each_line do |line| 
    if (line =~ /first_line/) .. (line =~ /end_line_I_care_about/) 
    do_something 
    end 
end 

括號是可選的,但它們提高了可讀性。

+0

你可以評論一下觸發器操作員泄氣嗎?我覺得它非常簡潔和有用,我不明白爲什麼你不會使用它,除非你的觀點是新的程序員不知道它,但是然後新的程序員不知道很多... – DavidG

3

是,Ruby支持觸發器:

str = "aaa 
ON 
bbb 
OFF 
cccc 
ON 
ddd 
OFF 
eee" 
str.each_line do |line| 
    puts line if line =~ /ON/..line =~ /OFF/ 
#puts line if line.match(/ON/)..line.match(/OFF/) #works too 
end 

輸出:

ON 
bbb 
OFF 
ON 
ddd 
OFF