Regex:传递一个查询字符串,当且仅当它包含一些后续参数



我正在尝试使用PaperTrail的过滤日志工具使用RegEx过滤掉特定的路径。我的日志字符串可能看起来像下面的一个:

NOT pass and NOT logged

Sep 03 10:12:40 lastmingear heroku/router:  at=info method=GET path="/orders/SOME_ID?key=USER_KEY" host=www.lastmingear.com...

应该通过,并被记录

Sep 03 10:12:40 lastmingear heroku/router:  at=info method=GET path="/orders/SOME_ID?key=USER_KEY&log=true" host=www.lastmingear.com...

唯一的区别是我希望记录它的路径有一个额外的参数log=true。因此,RegEx语句应该读作口头形式,如:

如果提供了key=USER_KEY,则不要传递到日志中,除非也有log=true

您可以使用正则表达式,但通常认为将查询字符串与这样的模式匹配是一种不好的做法。如果参数的顺序不同呢?如果它们之间还有其他参数呢?如果它们是url编码的呢?

相反,可以考虑解析查询字符串并分析键值对:

require 'uri'
def log?(log_line)
  path = log_line[/path="([^"]+)"/, 1]
  uri = URI(path)
  params = URI.decode_www_form(uri.query).to_h
  not params['key'] or params['log'] == 'true'
end

UPDATE:这是一个需要解决的棘手的正则表达式问题,因为没有真正的方法来表示if-this-then-that-or-etc。在正则表达式中。您可以使用断言,但它们只能帮到您这么多。本质上,您必须列举要传递的所有模式。我想强调的是,这是相当脆弱的,您需要随着时间的推移密切关注它,看看模式中是否有任何变化。

此模式使用数字订单号和可选查询字符串匹配/orders路由的日志行。如果提供了查询字符串,它必须匹配所提供的模式之一。如果提供了数字键号,则log必须为真。

/path="/orders/d+
  (?:?
    (?:(?!(?<=[?&])key=d+(?=[&"])).)*?
    |(.+?&)?log=true(&.+?)?
  )?
"/x

虽然我更喜欢@mwp的答案,因为他给出了原因,以下regex有什么问题:

/path="[^"]+?&log=true.*?"/

匹配所有非贪婪的非引号,直到你发现&log=true后面跟着任何非贪婪的东西,然后是一个结束的引号。

相关内容

  • 没有找到相关文章

最新更新