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>)*
),然后是 )
字符(与 \)
匹配)
)?
- 小组结束,一次或零次重复(可选)
我正在尝试通过 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>)*
),然后是)
字符(与\)
匹配)
)?
- 小组结束,一次或零次重复(可选)