如何为命名捕获组创建条件正则表达式?

How can I create a conditional regex for a named capturing group?

我们希望将我们的 PMDF 日志转储到 Splunk 中,我正在尝试解析 PMDF SMTP 日志,特别是消息,我遇到了一个问题,其中命名的捕获组 (dst_channel) 可能或者可能没有价值。到目前为止,这是我的正则表达式:

\d{2}\-\w{3}\-\d{4}\s\d{2}\:\d{2}\:\d{2}\.\d{2}\s(?P<src_channel>\w+)\s+(?P<dst_channel>\w+)\s(?P<code>\w+)\s(?P<bytes>\d+)\s(?P<from>\w.+)\srfc822

我能匹配到下面的消息,其中tcp_msx_out_2是dst_channel

02-Feb-2017 08:00:19.60 tcp_exempt   tcp_msx_out_2 E 2 mailman-bounces@list.xyz.com rfc822;user@xyz.com user@xyz.com <mailman.157.1486040414.29131.xxx@xxx.xyz.com> pmdf list.xyz.com ([x.x.x.x])

但是,我没有匹配以下不包含 dst_channel 值的日志:

02-Feb-2017 09:00:01.59 tcp_imap_int              Q 12 xxx@xyz.com rfc822;user@imap-internal.xyz.com user@imap.xyz.com <6940401380880269855036@PT-D69> pmdf  user@imap.xyz.com: smtp;452 4.2.2 Over quota

我拥有的下一个命名捕获组是第一个消息示例中的代码 E,第二个消息示例中的代码 Q),当 dst_channel 不存在时,正则表达式不会捕获所有代码。

我如何修改我的条件语句的正则表达式,以便如果 dst_channel 存在,它会获取值,但如果不存在,正则表达式将继续并能够始终如一地获取另一个命名的值我有捕获组吗?

如果我将 \w+ 更改为 \w*

,它会起作用
\d{2}\-\w{3}\-\d{4}\s\d{2}\:\d{2}\:\d{2}\.\d{2}\s(?P<src_channel>\w+)\s+(?P<dst_channel>\w*)\s(?P<code>\w+)\s(?P<bytes>\d+)\s(?P<from>\w.+)\srfc822

你可以测试一下here

我建议你使用

\d{2}-\w{3}-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d{2}\s+(?P<src_channel>\w+)(?:\s+(?P<dst_channel>\w+))?\s+(?P<code>\w+)\s+(?P<bytes>\d+)\s+(?P<from>\S+)\s+rfc822
                                                                   ^^^                       ^^  

参见regex demo

基本上,将所有 \s 替换为 \s+,并通过将 \s+ 和整个 dst 频道组与可选的 non-capturing 包装起来,使 dst 频道组成为可选频道组组.

此外,from 组模式应替换为 \S+(除空格外的一个或多个字符),因为您要匹配电子邮件,并且 .+ 可能 - 和通常它确实如此 - 过度匹配。