代码之家  ›  专栏  ›  技术社区  ›  wonderfulthunk

Ruby等价于“grep-c 5”来获取匹配周围的行上下文?

  •  6
  • wonderfulthunk  · 技术社区  · 14 年前

    我已经搜索了一点,但我肯定使用了错误的术语-Ruby是否有一种方法可以grep字符串/regex,并返回周围的5行(上面和下面)?我知道我可以打电话 "grep -C 5 ..." 或者甚至写我自己的方法,但这似乎是Ruby会有的,我只是没有使用正确的搜索词。

    3 回复  |  直到 9 年前
        1
  •  6
  •   Wayne Conrad    14 年前

    你可以用正则表达式来实现。下面是我们要搜索的字符串:

    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”定义一次模式:

    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"
    
        2
  •  2
  •   Richard Ryan    11 年前

    感谢上下文grep。我想我可以补充一下,当 比赛接近顶部或底部,你仍然想要所有的线你 即使没有可用的所有上下文行,也可以更改 上下文定义如下:

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

    默认情况下,匹配是贪婪的,所以如果部分或全部上下文行 有空,这就是你要抓住的。

        3
  •  0
  •   Pran    14 年前

    我认为你不能向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