Предположим, что строка выглядит следующим образом.
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
.