【问题标题】:Ruby Regex filter based on two hashes基于两个哈希的 Ruby Regex 过滤器
【发布时间】:2019-01-21 16:19:32
【问题描述】:

我正在尝试为 logsatash 构建一个过滤器。它需要在 Ruby 中。
过滤器采用 json 格式的元数据,并基于允许字段的另一个 json,从元数据中删除所有不匹配的字段。
过滤器的主线是进行评估。如果传递的元数据名称在允许的散列的键中,它应该评估为true。 (所有允许的哈希值都是true,如示例中所示,无关紧要)。
在允许的哈希中,可以有一个 globwildcard * 表示,在这种情况下它可以匹配任何字符串。
比如"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 方法是什么?

【问题讨论】:

  • 您需要解释"network.labels.*" 的含义。 (见我回答的第一句话。)
  • 感谢 cmets,我添加了对行为的解释。
  • 在您的编辑中说,“例如,"network.labels.*" 表示 "network.labels.one""network.labels.abc" 可以通过。”好的,但是为什么这意味着"instrument.network.one""instrument.network.two" 将“通过”,考虑到两者都包含附加字符串"instrument." 并且都不包含字符串"labels."?你给了@allowed,或者你能把它改成我的答案吗?
  • 元数据哈希包含更多条目,但你对我应该更简洁,编辑问题。我已经给出了允许值的元数据和哈希值,它们需要以准确的形式传递。感谢您的 cmets

标签: ruby regex


【解决方案1】:

我假设@allowed 应该如下。如果最后一个键不以“instrument”开头。或“.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} 

【讨论】:

    猜你喜欢
    • 2018-08-26
    • 2010-10-17
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2014-08-19
    相关资源
    最近更新 更多