我正在尝试使用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
后面跟着任何非贪婪的东西,然后是一个结束的引号。