如何在自定义 grok 模式中引用正则表达式组?

Posted

技术标签:

【中文标题】如何在自定义 grok 模式中引用正则表达式组?【英文标题】:How do I refer to a regex group inside a custom grok pattern? 【发布时间】:2017-08-02 22:01:06 【问题描述】:

我想在我的日志行中添加特定 URI 参数的字段

这是一个示例日志行:

2017-03-12 21:34:36 W3SVC1 webserver 1.1.1.1 GET /webpage.html param1=11111&param2=22222&param3=&param4=4444444 80 - 2.2.2.2 HTTP/1.1 Java/1.8.0_121 - - balh.com 200 0 0 311 244 247 - -

我想为 param1、param2、param3 和 param4 添加字段。

我正在使用这个 grok 过滤器:

  grok 
    match => [ "message", "(?<param1>param1=(.*?)&)"]
  

所以这个正则表达式使用一个捕获组来获取“param1=”和“&”之间的文本。但是 grok 忽略了捕获组并得到“param1=11111&”我只想捕获“111111”

如何说使用捕获组 1 或告诉 grok 使用我的正则表达式捕获组?

编辑 这几乎可以工作:

  grok 
    match => [ "message", "(?<param1>param1=(?<param1>.*?)&)"]
  

所以我我在这里所做的是使用两个命名组但具有相同的名称。问题是“param1”字段中每个组都有两个条目。一个用于“param1=11111&”,一个用于“11111”。我如何才能获得第二组?

【问题讨论】:

【参考方案1】:

这行得通:

  grok 
    match => [ "message", "(?:param1=(?<param1>.*?)&)"]
  

所以我我在这里所做的是使用一个非捕获组,其中嵌套了一个命名捕获组。所以父组的匹配被丢弃,嵌套的命名匹配是唯一返回的东西。

这是在做我认为它在做的事情还是这是错误的,它的愚蠢运气它做了我想要的?

【讨论】:

仅供参考:(?:...),一个非捕获组,在这里什么都不做,如果你删除它,模式将以同样的方式工作。仅当非捕获组包含交替或量化时(当您需要匹配 n 到 m 次出现、一次/零或多次,或一次或零次出现)时,才需要非捕获组。【参考方案2】:

如何说使用捕获组 1 或告诉 grok 使用我的正则表达式捕获组?

默认情况下,grok 只考虑命名的捕获组,编号的捕获组不会触发字段创建。如果要覆盖此行为,请将 named_captures_only 设置为 false

named_captures_only - 值类型为boolean - 默认值为true 如果是true,则只存储来自 grok 的命名捕获。

但是,使用命名捕获组并没有错(我会使用否定字符类 [^&amp;]*,而不是在其后使用 &amp; 的惰性匹配点):

\bparam1=(?<param1>[^&]*)

[^&amp;]* 匹配除 &amp; 之外的 0 个或多个字符,因此也匹配空参数(您可能希望通过将 * 更改为 + 来避免这种情况,或使用 keep_empty_captures 参数进行控制) 和字符串的末尾。

【讨论】:

这样做比我做的更快还是更少的资源消耗? 带有 greedy 量词的否定字符类的匹配速度比惰性量化点要快得多。我不相信实践中的性能差异很大,因为输入不是很长的字符串,但是,最佳实践是针对每种情况使用适当的工具(此处为模式),并且在正则表达式中,这意味着您需要当您需要匹配定义范围/集合中的字符或未定义的其他字符时,使用否定字符类。

以上是关于如何在自定义 grok 模式中引用正则表达式组?的主要内容,如果未能解决你的问题,请参考以下文章

干货 | Logstash自定义正则表达式ETL实战

Logstash笔记-----grok插件的正则表达式来解析日志

干货 | Logstash自定义正则表达式ETL实战

正则表达式之基础

LogStash使用笔记

ELK-logstash grok自定义正则