我有一個包含幾個不同部分的文本文件。每個部分都有一個標題,後面跟着實際的數據。例如:在ruby中拆分文本文件
Header1
x,y,z
x,y,z
x,y,z
Header2
a,b,c
a,b,c
a,b,c
我想通過在文件中一次通過閱讀和目前根據各部分的數據做不同的事情。我知道如何解析數據,但是我很難弄清楚如何編寫邏輯「這樣做直到碰到Header2,然後做一些其他的事情,直到Header3等。」
我使用紅寶石,我還沒有真正遇到過這樣做的任何例子。有什麼建議麼?
我有一個包含幾個不同部分的文本文件。每個部分都有一個標題,後面跟着實際的數據。例如:在ruby中拆分文本文件
Header1
x,y,z
x,y,z
x,y,z
Header2
a,b,c
a,b,c
a,b,c
我想通過在文件中一次通過閱讀和目前根據各部分的數據做不同的事情。我知道如何解析數據,但是我很難弄清楚如何編寫邏輯「這樣做直到碰到Header2,然後做一些其他的事情,直到Header3等。」
我使用紅寶石,我還沒有真正遇到過這樣做的任何例子。有什麼建議麼?
在最簡單的,你可以做這樣的事情:
# 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
會這樣的工作?
File.open('datafile').each_line do |s|
if s =~ /^headerpattern$/
#Start a new parsing block
...
else
#Parse data
...
end
end
使用對象的解決方案。對於每一行你問每個解析器是否有一個新的節已經開始解析器可以解析。
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
這與SébastienLe Callonnec的解決方案基本相同,但更簡潔,更易於擴展更多部分。 – 2012-04-07 21:41:15
這很棒,正如你所說,它是一個更清潔,更可擴展的解決方案。也就是說,我接受了SébastienLe Callonnec的解決方案,因爲這是我最終用來完成工作的方式(我只有三個Header部分可以處理)。 – 2012-04-07 23:24:49
在我的情況「標頭」是形式以下字符串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
,但也有一些先決條件:我總是確保該文件的第一行包含一個頭。我也沒有關閉文件(這一定會在一天內將我的業力拉到零)。
看起來像這樣會特別簡單,如果處理一次只處理一個輸入行,而且如果除了計算每個段的自動彙總統計信息外,還會稍微複雜一些。這兩種情況都適合您的任務嗎? – hardmath 2012-04-07 21:09:48