Ruby извлекает несколько строк перед шаблоном регулярного выражения - PullRequest
0 голосов
/ 28 сентября 2018

Я слежу за файлом и ловлю регулярное выражение.Однако я хочу 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 голосов
/ 29 сентября 2018

Предположим, что строка выглядит следующим образом.

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.

0 голосов
/ 28 сентября 2018

Я бы использовал регулярное выражение с последующей фильтрацией результата:

input.
  scan(/(tx=\d+).*?Response:\s+(\d+)/m).
  select { |_, resp| resp == '201' }.
  map(&:first)
#⇒ ["tx=1111"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...