Multi-level parsing text

可紊 提交于 2019-12-25 18:39:02

问题


The last time I had a problem: Parsing and structuring of a text file Now I imagine complicated conditions. For example. I had a text file with next contain:

Head 1
Subhead 1
a 10
b 14
c 88
Subhead 2
a 15
b 16
c 17
d 88
Subhead 3
a 55
b 36
c 87
Head 4
Subhead 1
r 32
t 55
s 79
r 22
t 88
y 53
o 78
p 90
m 44
Head 53
Subtitle 1
y 22
b 33
Subtitle 2
a 88
g 43
r 87
Head 33
Subhead 1 
z 11
d 66
v 88
b 69
Head 32
Subhead 1
n 88
m 89
b 88
Subhead 2
b 88
m 43

Now I need structure text to next plane. I want to get next data:

Head 1, Subhead 1, c 88
Head 1, Subhead 2, d 88
Head 4, Subhead 1, t 88
Head 53, Subhead 2, a 88
Head 33, Subhead 1, v 88
Head 32, Subhead 1, n 88
Head 32, Subhead 1, b 88
Head 32, Subhead 2, b 88

That is, I want to get all the rows with 88 indicating the head and subhead.

My actions:

lines = File.open("file.txt").to_a
lines.map!(&:chomp) # remove line breaks

current_head = ""
res = []

lines.each do |line|
  case line
  when /Head \d+/
    current_head = line
  when /Subhead/
    sub = line
  when /\w{1} 88/
  num = line
    res << "#{current_head}, #{sub}, #{num}"
  end
end

puts res

When I use this method I get a string without NUM values.

Whether to perform my task means "case when" possible?


回答1:


The variables declared inside the each block do not persist between iterations. When the iteration ends, those variables disappear, which is why you're losing the previous sub value. To fix it, move the sub variable to the outer scope by initializing it before the each, just like you have with current_head:

current_head = ""
current_sub = ""
res = []

lines.each do |line|
  case line
  when /Head \d+/
    current_head = line
  when /Subhead/
    current_sub = line
  when /\w{1} 88/
  num = line
    res << "#{current_head}, #{current_sub}, #{num}"
  end
end

See it on repl.it: https://repl.it/GBKn




回答2:


If you want to keep variables between two iterations, you could use instance variables.

File.foreach is the recommended way of reading a file :

res = []
File.foreach("file.txt") do |line|
  line.chomp!
  case line
  when /Head \d+/
    @current_head = line
  when /Sub(head|title)/
    @sub = line
  when /\w 88/
    num = line
    res << "#{@current_head}, #{@sub}, #{num}"
  end
end
puts res


来源:https://stackoverflow.com/questions/42513224/multi-level-parsing-text

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!