6

我已经对此进行了一些搜索,但我必须使用错误的术语 - ruby​​ 是否有办法 grep 字符串/正则表达式并返回周围的 5 行(上方和下方)?我知道我可以调用"grep -C 5 ..."甚至编写自己的方法,但似乎 ruby​​ 会有一些东西,而我只是没有使用正确的搜索词。

4

3 回答 3

6

您可以使用正则表达式来完成。这是我们要搜索的字符串:

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 对我来说是“\n”,但对你来说可能是“\r\n”。我会坚持下去:

EOL = '\n'

为了简化正则表达式,我们将只定义一次“上下文”的模式:

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

我们将搜索包含单词“fifth”的任何行。请注意,此正则表达式必须抓取整行,包括行尾,才能正常工作:

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

最后,进行搜索并显示结果:

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"
于 2010-05-03T22:02:45.907 回答
2

感谢上下文 grep。我想我可以补充一下,当匹配接近顶部或底部时,即使没有所有可用的 CONTEXT_LINES 行,您仍然希望获得所有行,您可以将 CONTEXT 的定义更改为如下:

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

默认情况下,匹配是贪婪的,所以如果部分或全部 CONTEXT_LINES 行可用,那就是你要抓住的。

于 2013-09-03T21:53:43.127 回答
0

我认为您不能向 grep 提供 args;基于api

你总是可以写一个方法。类似这样的东西:

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
于 2010-05-03T20:41:33.090 回答