Misha1991 Misha1991 -4 years ago 145
Ruby Question

Multi-level parsing text

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?

Answer Source

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download