2012-04-07 124 views
2

我有一個包含幾個不同部分的文本文件。每個部分都有一個標題,後面跟着實際的數據。例如:在ruby中拆分文本文件

Header1 
x,y,z 
x,y,z 
x,y,z 
Header2 
a,b,c 
a,b,c 
a,b,c 

我想通過在文件中一次通過閱讀和目前根據各部分的數據做不同的事情。我知道如何解析數據,但是我很難弄清楚如何編寫邏輯「這樣做直到碰到Header2,然後做一些其他的事情,直到Header3等。」

我使用紅寶石,我還沒有真正遇到過這樣做的任何例子。有什麼建議麼?

+0

看起來像這樣會特別簡單,如果處理一次只處理一個輸入行,而且如果除了計算每個段的自動彙總統計信息外,還會稍微複雜一些。這兩種情況都適合您的任務嗎? – hardmath 2012-04-07 21:09:48

回答

1

在最簡單的,你可以做這樣的事情:

# Process lines for header1 
def do_header1(line) 
    puts line.split(/,/).join("|") 
end 

# Process lines for header2 
def do_header2(line) 
    puts line.split(/,/).map{ |e| e.upcase}.join(",") 
end 

header1 = false 
header2 = false 

# Main loop 
File.open("file.txt").each_line do |line| 
    if line.chomp == 'Header1' # or whatever match for header1 
    header1 = true 
    header2 = false 
    next 
    end 
    if line.chomp == 'Header2' # or whatever match for header2 
    header1 = false 
    header2 = true 
    next 
    end 

    do_header1(line) && next if header1 
    do_header2(line) && next if header2 

end 

如果頭的數量過高,你就可以開始以整數跟蹤頭:

header = -1 

# Main loop 
File.open("file.txt").each_line do |line| 
    if line.chomp == 'Header1' # or whatever match for header1 
    header = 1 
    next 
    end 
    if line.chomp == 'Header2' # or whatever match for header2 
    header = 2 
    next 
    end 

    do_header1(line) && next if header == 1 
    do_header2(line) && next if header == 2 

end 
0

會這樣的工作?

File.open('datafile').each_line do |s| 
    if s =~ /^headerpattern$/ 
    #Start a new parsing block 
    ... 
    else 
    #Parse data 
    ... 
    end 
end 
1

使用對象的解決方案。對於每一行你問每個解析器是否有一個新的節已經開始解析器可以解析。

class Section1Parser 
    def section? potential_header 
    potential_header.chomp == 'Header1' 
    end 
    def parse line 
    puts "Section 1: #{line.split(/,/).join("|")}" 
    end 
end 

class Section2Parser 
    def section? potential_header 
    potential_header.chomp == 'Header2' 
    end 
    def parse line 
    puts "Section 2: #{line.split(/,/).join("|")}" 
    end 
end 

parsers = [Section1Parser.new, Section2Parser.new] 
selected_parser = nil 

File.open("c:\\temp\\file.txt").each_line do |line| 
    if new_parser_detected = parsers.detect {|p| p.section? line } 
    selected_parser = new_parser_detected 
    next # skip header 
    end 
    selected_parser.parse line if selected_parser 
end 
+0

這與SébastienLe Callonnec的解決方案基本相同,但更簡潔,更易於擴展更多部分。 – 2012-04-07 21:41:15

+0

這很棒,正如你所說,它是一個更清潔,更可擴展的解決方案。也就是說,我接受了SébastienLe Callonnec的解決方案,因爲這是我最終用來完成工作的方式(我只有三個Header部分可以處理)。 – 2012-04-07 23:24:49

0

在我的情況「標頭」是形式以下字符串OBJECT ObjectType ObjectNumber ObjectName

if File.exist?("all.txt") then 
    object_file = File 

    File.open("all.txt").each_line do |line| 
     file_name = case 
      when line.match('^OBJECT Table.*') 
       "TAB" + line.split[2] + ".TXT" 
      when line.match('^OBJECT Form.*') 
       "FOR" + line.split[2] + ".TXT" 
      when line.match('^OBJECT Report.*') 
       "REP" + line.split[2] + ".TXT" 
      when line.match('^OBJECT Dataport.*') 
       "DAT" + line.split[2] + ".TXT" 
      when line.match('^OBJECT XMLPort.*') 
       "XML" + line.split[2] + ".TXT" 
      when line.match('^OBJECT Codeunit.*') 
       "COD" + line.split[2] + ".TXT" 
      when line.match("^OBJECT MenuSuite.*") 
       "MEN" + line.split[2] + ".TXT" 
      when line.match('^OBJECT Page.*') 
       "PAG" + line.split[2] + ".TXT" 
      when line.match('^OBJECT Query.*') 
       "QUE" + line.split[2] + ".TXT" 
     end 

     unless file_name.nil? 
      File.exist?(file_name) { File.delete(file_name) } 
      object_file = File.open(file_name,"w") 
     end 

     object_file.write(line) 
    end 
end 

,但也有一些先決條件:我總是確保該文件的第一行包含一個頭。我也沒有關閉文件(這一定會在一天內將我的業力拉到零)。