Фильтр Ruby Regex на основе двух хешей - PullRequest
0 голосов
/ 21 января 2019

Я пытаюсь построить фильтр для logsatash. Это должно быть в Ruby.
Фильтр принимает метаданные в формате json и на основе другого json разрешенных полей удаляет все несоответствующие поля из метаданных.
Основная линия фильтра - сделать оценку. Если переданное имя метаданных находится в ключах разрешенного хэша, оно должно быть равно true. (Все значения разрешенного хэша true как в примере и не имеют значения).
В разрешенном хэше может быть glob , представленный подстановочным знаком *, в таком случае он может соответствовать любой строке.
Например, "instrument.network.*" означает, что "instrument.network.one" или "instrument.network.abc" могут пройти.
Но если нет *, как в "event.type", может пройти только такая точная строка, но не "event.type.abc". Другими словами, * представляет любое количество символов так же, как в регулярных выражениях.
Упрощенный код выглядит так:

# input data
metadata = {"event.type"=>"message", "instrument.network.one"=>false, "instrument.network.two"=>false, "other.meta"=>true}
@allowed = {"timestamp"=>true, "event.type"=>true, "network.labels.*"=>true}

metadata.each do |key, val|
  # evaluation to be worked out
  evaluation = (@allowed.has_key? key)
  puts "the #{key} is allowed?: #{evaluation}"
  # metadata clearence
  metadata.delete(key) if !evaluation
end
puts "metadata after clearence: #{metadata}"

На данный момент вывод этого кода:

the event.type is allowed?: true
the instrument.network.one is allowed?: false
the instrument.network.two is allowed?: false
the other.meta is allowed?: false
metadata after clearence: {"event.type"=>"message"}

Но мне нужно, чтобы подстановочный знак, передаваемый из "network.labels.*", имел такой вывод:

the event.type is allowed?: true
the instrument.network.one is allowed?: true
the instrument.network.two is allowed?: true
the other.meta is allowed?: false
metadata after clearence: {"event.type"=>"message", "instrument.network.one"=>false, "instrument.network.two"=>false}

Я пытаюсь использовать Regexp.union(@allowed) =~ key, но не могу заставить его работать таким образом. Я пробовал другие рубиновые трюки, такие как .find и т. Д., Но не ожидал результата. Есть примеры использования одного регулярного выражения, поиск в массиве строк, но не наоборот.
Каким был бы Ruby способ построить такой фильтр?

1 Ответ

0 голосов
/ 21 января 2019

Полагаю, @allowed должно быть следующим. Если последний ключ не начинается с «инструмента». или ".labels", назначение подстановочного знака "*" неясно.

@allowed = { "timestamp"=>true, "event.type"=>true,
             "instrument.network.*"=>true }

arr = @allowed.map { |k,_|
  Regexp.new(k.gsub('.', '\.').sub('*', '.*')) }
  #=> [/timestamp/, /event\.type/, /instrument\.network\..*/] 
r = /\A#{Regexp.union(arr)}\z/
  #=> /\A(?-mix:(?-mix:timestamp)|(?-mix:event\.type)|(?-mix:instrument\.network\..*))\z/ 
metadata.select do |k,_|
  res = k.match?(r)
  puts "#{k} is allowed?: #{res}"
  res
end
event.type is allowed?: true
instrument.network.one is allowed?: true
instrument.network.two is allowed?: true
other.meta is allowed?: false
  #=> {"event.type"=>"message", "instrument.network.one"=>false, ] 
  #    "instrument.network.two"=>false} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...