Read n lines above the current line in Ruby?

I have a data file that looks like this:

Things β”œβ”€β”€ Foo β”‚  β”œβ”€β”€ 1. Item One β”‚  β”œβ”€β”€ 2. Item Two β”‚  β”œβ”€β”€ 3. Item Three β”‚  β”œβ”€β”€ 4. Item Four β”‚  β”œβ”€β”€ 5. Item Five β”‚  └── 6. Item Six β”œβ”€β”€ Bar β”‚  β”œβ”€β”€ 1. Item Seven β”‚  β”œβ”€β”€ 2. Item Eight β”‚  β”œβ”€β”€ 3. Item Nine 

What I'm trying to do is find a specific line, the number associated with it, as well as a subheading that is part of ('Foo' or 'Bar')

Pretty easy to grab the item and number:

 str = "Item One" data.each_line do |line| if line =~ /#{str}/ /(?<num>\d).\s(?<item>.*)/ =~ line end end 

But I'm not sure how to get the subtitle. I thought that as soon as I found the line, I could count from this point using the number. Are there any reading lines or a search command or some of them that can do this?

Appreciate the help!

+4
source share
2 answers

I came up with below, this seems to work:

 data = <<-EOF Things β”œβ”€β”€ Foo β”‚ β”œβ”€β”€ 1. Item One β”‚ β”œβ”€β”€ 2. Item Two β”‚ β”œβ”€β”€ 3. Item Three β”‚ β”œβ”€β”€ 4. Item Four β”‚ β”œβ”€β”€ 5. Item Five β”‚ └── 6. Item Six β”œβ”€β”€ Bar β”‚ β”œβ”€β”€ 1. Item Seven β”‚ β”œβ”€β”€ 2. Item Eight β”‚ β”œβ”€β”€ 3. Item Nine EOF str = "Item One" data.lines.each_with_index do |line, i| if /(?<num>\d)\.\s+#{str}/ =~ line /(?<var>\w+)/ =~ data.lines[i - (n = $~[:num]).to_i] p [n, str, var] # ["1", "Item One", "Foo"] end end 

(n = $~[:num]) needed to save the captured num value from

 if /(?<num>\d)\.\s+#{str}/ =~ line 

into a variable (say n ), since the last matching data represented by the global variable $~ will be overwritten during the next regular expression contained in the statement

 /(?<var>\w+)/ =~ data.lines[i - (num = $~[:num]).to_i] 

and if we do not save it for later use, we will lose the captured num value.

+9
source

Here's another way (using @Wand data ):

 LAZY_T = "β”œβ”€β”€ " target = "Item Four" str = data.split(/\n#{LAZY_T}/).find { |s| s =~ /\b#{target}\b/ } str && [str[/[a-zA-Z]+/], str[/(\d+)\.\s#{target}\b/,1]] #=> ["Foo", "4"] 

The first line extends the applicable part of the line ( "Foo" or "Bar" ), if any. The second line retrieves the two desired items.

Note:

 LAZY_T.split('').map(&:ord) #=> [9500, 9472, 9472, 32] 
+2
source

All Articles