Я не использую rubocop, но я проверил следующее с этими данными:
data = <<FILE
10.6.246.103 - - [23/Apr/2018:20:30:39 +0300] "POST /test/2/messages HTTP/1.1" 200 48 0.0498
10.6.246.101 - - [23/Apr/2018:20:30:42 +0300] "POST /test/2/run HTTP/1.1" 200 - 0.2277
12.55.123.255 - - Hello
FILE
с использованием String#gsub!
и Enumerable#select
( Сообщений AbcSize 3 )
def task_2(str)
str.each_line.select do |x|
# Without named groups
# x.gsub!(/\A([\d+\.\d+]+).*(?<=\[)(.*)(?=\]).*(?<=\s)((?:\/\w+)*?)(?=\s).*\z/m,
# '\2 FROM \1 TO \3')
x.gsub!(/\A(?<ip>[\d+\.\d+]+).*(?<=\[)(?<date_time>.*)(?=\]).*(?<=\s)(?<address>(?:\/\w+)*?)(?=\s).*\z/m,
'\k<date_time> FROM \k<ip> TO \k<address>')
end
end
task_2(data)
# => ["23/Apr/2018:20:30:39 +0300 FROM 10.6.246.103 TO /test/2/messages",
# "23/Apr/2018:20:30:42 +0300 FROM 10.6.246.101 TO /test/2/run"]
Здесь мы используем String#gsub!
с заменой шаблона, которая будет возвращать nil
, если замена не была сделана, таким образом, отклоняя ее от Enumerable#select
.
Аналогичное решение, хотя, вероятно, и менее эффективное, с использованием String#match
, Enumerable#map
и Array#compact
( Reports AbcSize 7.14 )
def task_2(str)
str.each_line.map do |x|
match = x.match(/\A(?<ip>[\d+\.\d+]+).*(?<=\[)(?<date_time>.*)(?=\]).*(?<=\s)(?<address>(?:\/\w+)*?)(?=\s)/)
"#{match['date_time']} FROM #{match['ip']} TO #{match['address']}" if match
end.compact
end
Здесь мывы используете String#match
для извлечения данных о совпадении, а затем подтверждаете совпадение и выводите нужный формат, если есть совпадение.Строка, которая не соответствует, будет выводить nil
, и, таким образом, мы compact
Array
удаляем значения nil
.
Другой вариант может быть просто scan
все String
всесразу и выделите соответствующие группы: ( Сообщает AbcSize 5 )
def task_2(str)
str.scan(/^([\d+\.\d+]+).*(?<=\[)(.*)(?=\]).*(?<=\s)((?:\/\w+)*?)(?=\s).*$/)
.map {|a| "#{a[1]} FROM #{a[0]} TO #{a[2]}"}
end
Может сделать последнюю такую же низкую, как 2,24 через
def task_2(str)
r = []
str.scan(/^([\d+\.\d+]+).*(?<=\[)(.*)(?=\]).*(?<=\s)((?:\/\w+)*?)(?=\s).*$/) do |ip, date_time, address |
r << "#{date_time} FROM #{ip} TO #{address}"
end
r
end