Ruby在正则表达式模式之前获取几行

时间:2018-09-28 10:04:19

标签: ruby regex

我正在尾随一个文件并捕获一个正则表达式。但是我要在常规模式之前输入4行。

示例输入:

2018-09-28 00:00:01 INFO  .....
2018-09-28 00:00:01 INFO  tx=1111 ....
2018-09-28 00:00:01 INFO  - Invoking API time=515ms
     -> Invoked URL: 'http://........'
     -> Authorization: ....
     -> Request: blah blah request
     <- Response: 201 - Success

我想为每个响应获取tx = 1111:201

可以这样做吗?我可以使用正向回溯吗?

2 个答案:

答案 0 :(得分:0)

我将使用regexp,然后过滤结果:

input.
  scan(/(tx=\d+).*?Response:\s+(\d+)/m).
  select { |_, resp| resp == '201' }.
  map(&:first)
#⇒ ["tx=1111"]

答案 1 :(得分:0)

假设字符串如下。

str =<<BITTER_END
2018-09-28 00:00:01 INFO  .....
2018-09-28 00:00:01 INFO  tx=1111 ....
2018-09-28 00:00:01 INFO  - Invoking API time=515ms
     -> Invoked URL: 'http://........'
     -> Authorization: ....
     -> Request: blah blah request
     <- Response: 201 - Success
2018-09-28 00:00:01 INFO  .....
2018-09-28 00:00:01 INFO  tx=1112 ....
2018-09-28 00:00:01 INFO  - Invoking API time=515ms
     -> Invoked URL: 'http://........'
     -> Authorization: ....
     -> Request: blah blah request
     <- Response: 202 - Success
2018-09-28 00:00:01 INFO  .....
2018-09-28 00:00:01 INFO  tx=1113 ....
2018-09-28 00:00:01 INFO  - Invoking API time=515ms
     -> Invoked URL: 'http://........'
     -> Authorization: ....
     -> Request: blah blah request
     <- Response: 201 - Success
BITTER_END

我的理解是,我们希望在tx之后(几行之后)返回<- Response: 201的值(数组)。如果正确,我们希望返回["1111", "1113"],但不返回"1112",因为后面跟着<- Response: 202

如果我们首先反转字符串,使它显示如下(puts str.reverse的结果),则可以使用简单的正则表达式来完成。

sseccuS - 102 :esnopseR -<
tseuqer halb halb :tseuqeR >-
.... :noitazirohtuA >-
'........//:ptth' :LRU dekovnI >-
sm515=emit IPA gnikovnI -  OFNI 10:00:00 82-90-8102
.... 3111=xt  OFNI 10:00:00 82-90-8102
.....  OFNI 10:00:00 82-90-8102
sseccuS - 202 :esnopseR -<
tseuqer halb halb :tseuqeR >-
.... :noitazirohtuA >-
'........//:ptth' :LRU dekovnI >-
sm515=emit IPA gnikovnI -  OFNI 10:00:00 82-90-8102
.... 2111=xt  OFNI 10:00:00 82-90-8102
.....  OFNI 10:00:00 82-90-8102
sseccuS - 102 :esnopseR -<
tseuqer halb halb :tseuqeR >-
.... :noitazirohtuA >-
'........//:ptth' :LRU dekovnI >-
sm515=emit IPA gnikovnI -  OFNI 10:00:00 82-90-8102
.... 1111=xt  OFNI 10:00:00 82-90-8102
.....  OFNI 10:00:00 82-90-8102

我们的正则表达式如下。

r = /
    [ ]102[ ]:esnopseR[ ]-<  # match reverse of `'<- Response: 201'      
    .+?                      # match one or more characters, lazily
    [ ]                      # match a space
    (\d+)                    # match one or more digits in capture group 1
    =xt[ ][ ]OFNI            # match '=xt  OFNI'
    /xm                      # free-spacing and multiline modes

(我已经在自由空间模式下编写了它,以便记录每个元素。) 1 然后我们可以使用String#scan提取所需的值。

str.reverse.scan(r).flatten.map(&:reverse).reverse
  #=> ["1111", "1113"]

我们首先获得以下内容。

str.reverse.scan(r)
  #=> [["3111"], ["1111"]]

根据需要["1111", "1113"],我们必须展平此数组,反转每个字符串,然后反转反转的字符串的顺序。

1。该正则表达式通常用/ 102 :esnopseR -<.+? (\d+)=xt OFNI/m表示。在自由间距模式下删除空格,这就是为什么使用/x选项时每个空格都包含在字符类中的原因。为了最大程度地减少错误,最好写/#{'<- Response: 201 '.reverse}.+? (\d+)#{'INFO tx='.reverse}/m