2012-04-07 86 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 

,但也有一些先决条件:我总是确保该文件的第一行包含一个头。我也没有关闭文件(这一定会在一天内将我的业力拉到零)。