Is the Ruby equivalent of "grep -C 5" to get the context of the lines around the match?

I searched this a bit, but I have to use the wrong terms. Does Ruby have a grep way for string / regex, and also return 5 outer lines (above and below)? I know that I can just call "grep -C 5 ..." or even write my own method, but it looks like the ruby ​​will have something, and I just do not use the correct search conditions.

+6
ruby regex grep lines
source share
3 answers

You can do this with a regex. Here is the line we want to find:

 s = %{The first line The second line The third line The fourth line The fifth line The sixth line The seventh line The eight line The ninth line The tenth line } 

EOL is "\ n" for me, but for you it could be "\ r \ n". I will stick with it in constant:

 EOL = '\n' 

To simplify the regular expression, we will define the template for the context only once:

 CONTEXT_LINES = 2 CONTEXT = "((?:.*#{EOL}){#{CONTEXT_LINES}})" 

And we will search for any string containing the word "fifth". Note that this regex must capture the entire line, including the end of the line, for it to work:

 regexp = /.*fifth.*#{EOL}/ 

Finally, do a search and show the results:

 s =~ /^#{CONTEXT}(#{regexp})#{CONTEXT}/ before, match, after = $1, $2, $3 p before # => "The third line\nThe fourth line\n" p match # => "The fifth line\n" p after # => "The sixth line\nThe seventh line\n" 
+6
source share

Thanks for the context grep. I thought I could add that when a match approaches the top or bottom, and you still want all the lines you can get even without all the available CONTEXT_LINES lines, you can change the definition of CONTEXT to be as follows:

 CONTEXT = "((?:.*#{EOL}){0,#{CONTEXT_LINES}})" 

By default, matches are greedy, so if part or all of the CONTEXT_LINES lines are available, what will you capture.

+2
source share

I do not think you can provide args for grep; based on api .

You can always write a method. Something like that:

 def new_grep(enum, pattern, lines) values = enum.grep(/pattern/).map do |x| index = enum.index(x) i = (index - lines < 0) ? 0 : index - lines j = (index + lines >= enum.length) ? enum.length-1 : index + lines enum[i..j] end return values.flatten.uniq end 
0
source share

All Articles