2012-04-07 4 views
2

여러 섹션으로 구성된 텍스트 파일이 있습니다. 각 섹션에는 실제 데이터가 오는 헤더가 있습니다. 예를 들면 다음과 같습니다.루비로 텍스트 파일을 분할합니다.

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

한 번에 파일을 읽고 각 섹션 아래에있는 데이터와 다른 작업을하고 싶습니다. 데이터를 구문 분석하는 방법을 알고 있지만 "Header2를 때릴 때까지 이것을 수행 한 다음 Header3까지 다른 작업을 수행하는 등의 논리를 코딩하는 방법을 알아내는 데 문제가 있습니다."

저는 루비를 사용하고 있습니다. 실제로이 작업을 수행 한 예가 없습니다. 어떤 제안?

+0

처리가 한 번에 하나의 입력 행을 처리하고 게다가 각 섹션에 대한 요약 통계를 단독으로 계산하는 경우 약간 더 복잡하면 특히 간단 할 것 같습니다. 이러한 시나리오 중 하나가 작업에 잘 맞습니까? – hardmath

답변

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ébastien Le Callonnec의 솔루션과 동일하지만 더 많은 섹션으로 더 깔끔하고 쉽게 확장 할 수 있습니다. –

+0

이것은 훌륭하고 앞에서 말한 것처럼 더 깔끔하고 확장 가능한 솔루션입니다. 즉, 세바스티앙 르 캘론 크 (Sebastien Le Callonnec)의 솔루션을 받아 들였습니다. 그 이유는 제가 작업을 끝내기 위해 사용하기 시작한 것이기 때문입니다. (단 3 개의 헤더 섹션 만 처리해야했기 때문입니다.) –

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 

를 다음의 형태였다 그러나 일부 전제 조건이 있습니다 나는 항상 파일의 첫 번째 줄은 헤더를 포함 할 것을 확신합니다. 나는 또한 파일을 닫지 않을 것이다 (이것은 분명히 나의 운명을 0 일로 끌 것이다).