Grok pattern/Regex 解析带有嵌套括号的字符串

Grok pattern/Regex to parse string with nested parenthesis

我正在尝试通过 Grok/Regex 解析存在于 () 之间的日志消息中的几个动态字符串。例如(下图SenderPartyName):

2021/05/23 16:01:26.094 High Messaging.Message.Delivered Id(ci1653336085475.12327434@test_te) MessageId(EPIUM#1130754#84601671) SenderPartyName(Mcdonalds (CFH) Restaurant Glen) ReceiverPartyName(TEST_HERE_AGAIN) SenderRoutingId(08Mdsfkm853)

我想从遵循 () 格式的字符串中解析出每个键值。到目前为止,这是我的 grok 模式。我一直在用 https://grokdebug.herokuapp.com/

进行测试
%{DATESTAMP:ts} %{WORD:loglevel} %{DATA:reason}\s ?(Id\(%{DATA:id}\))? ?(MessageId\(%{DATA:originalmessageid}\))? ?(SenderPartyName\((?<senderpartyname>.+?\).+?)\))? ?(ReceiverPartyName\(%{DATA:receiverpartyname}\))? ?(SenderRoutingId\(%{DATA:senderroutingid}\))?

当嵌套字符串中有 () 时,此方法有效,如下所示: Mcdonalds (CFH) Restaurant Glen

...但它是动态的并且可能在没有 () 的情况下出现,如下所示:Mcdonalds Restaurant Glen

正在尝试构建正则表达式以说明这部分 grok 模式的两种情况:

?(SenderPartyName\((?<senderpartyname>.+?\).+?)\))?

目前这会像这样解析非括号的情况:

  "senderpartyname": "Mcdonalds Restaurant Glen) ReceiverPartyName(TEST_HERE_AGAIN"

..根据字符串,所需状态是以下之一:

"senderpartyname": "Mcdonalds Restaurant Glen"

"senderpartyname": "Mcdonalds (CFH) Restaurant Glen"

您可以使用

%{DATESTAMP:ts}\s+%{WORD:loglevel}\s+%{DATA:reason}\s+Id\(%{DATA:id}\)(?:\s+MessageId\(%{DATA:originalmessageid}\))?(?:\s+SenderPartyName(?<senderpartyname>\((?:[^()]++|\g<senderpartyname>)*\)))?(?:\s+ReceiverPartyName\(%{DATA:receiverpartyname}\))?(?:\s+SenderRoutingId\(%{DATA:senderroutingid}\))?

请注意,我对其进行了修改,以便所有可选字段都匹配一个或多个空格,并将字段作为强制模式,但它们作为一个序列是可选的,这使得匹配更有效。

主要改变的是(?:\s+SenderPartyName(?<senderpartyname>\((?:[^()]++|\g<senderpartyname>)*\)))?,它匹配

  • (?: - non-capturing 组的开始:
    • \s+ - 一个或多个空格
    • SenderPartyName - 固定字
    • (?<senderpartyname>\((?:[^()]++|\g<senderpartyname>)*\)) - 组“senderpartyname”:((与 \( 匹配),然后 ( 和 [=19 以外的任何字符重复零次或多次=] 或递归的组“senderpartyname”模式(参见 (?:[^()]++|\g<senderpartyname>)*),然后是 ) 字符(与 \) 匹配)
  • )? - 小组结束,一次或零次重复(可选)