条件正则表达式,如何提取匹配的子集?

Posted

技术标签:

【中文标题】条件正则表达式,如何提取匹配的子集?【英文标题】:Conditional Regex, how to extract a subset of a match? 【发布时间】:2013-08-08 17:00:01 【问题描述】:

我有系统日志字符串,如下所示:

lwiod[2469]: S-1-5-21-2071757552-4033313730-2397045981-3628|0xC94F000|LOGON|STATUS_SUCCESS|10.10.19.10|10.10.42.40|COMPANY\USERNAME
lwiod[2469]: S-1-5-21-2071757552-4033313730-2397045981-3628|0xC94F000|LOGON|STATUS_SUCCESS|10.10.19.10|10.10.42.40|USERNAME@COMPANY
lwiod[2469]: S-1-5-21-2071757552-4033313730-2397045981-3628|0xC94F000|LOGON|STATUS_SUCCESS|10.10.19.10|10.10.42.40|UNKNOWN

我有一个正则表达式来捕获我需要的所有内容,如下所示:

lwiod\[([0-9]+)\]: (.*)\|(.*)\|LOGON\|STATUS_(.*)\|(.*)\|(.*)\|(COMPANY\\.*|.*\@COMPANY|UNKNOWN)

我还需要该正则表达式做的是仅在字段 7 中给我 USERNAME OR UNKNOWN,我不想要 COMPANY(这是一个 AD 域名),但我遇到了麻烦。

字段 1 为 S-1-5-21-2071757552-4033313730-2397045981-3628,2 为 0xC94F000,...,7 为 USERNAME 或 UNKNOWN。

谢谢!

【问题讨论】:

你使用的是什么正则表达式引擎? 它是基于 SIEM 的 PCRE。我还应该澄清一下,我也需要字段 1 到 6,所以我确实需要这些。我正在尝试做的也是获取字段 7,并且只有用户名或未知,而不必使用编程语言。这些是发送到商业正则表达式解析器的系统日志,除了正则表达式之外我没有其他方法可以调整。 【参考方案1】:

好的,我猜你可能会使用这样的东西?

lwiod\[([0-9]+)\]: (.*)\|(.*)\|LOGON\|STATUS_(.*)\|(.*)\|(.*)\|(?:COMPANY\\)?(UNKNOWN|[^@]+)(?:@)?

从您当前的正则表达式来看,COMPANY 似乎是原样,所以我假设相同。否则,我想你可以使用

lwiod\[([0-9]+)\]: (.*)\|(.*)\|LOGON\|STATUS_(.*)\|(.*)\|(.*)\|(?:[^\\]*\\)?(UNKNOWN|[^@]+)(?:@)?

【讨论】:

这在我的测试反向引用中不起作用 7 有 USERNAME 然后是 lwiod[2469]: S-1-5-21-2071757552-4033313730-2397045981-3628|0xC94F000|LOGON|STATUS_SUCCESS|10.10.19.10|10.10.42.40|USERNAME 然后是 UNKNOWN...这是不对的。 好点,但这仅适用于应用于整个字符串块的情况。如果您逐行应用它,它将按预期工作。如果将其应用于整个块,则需要在否定类中添加更多字符,即 \n 以避免换行符。见here。 \n 将跳过最后一行,因为您在最后一行没有换行符...您想使用$ @abc123 不确定您的意思。最后一行对我来说很好......编辑:请参阅我之前评论中的链接。 这是因为您正在使用标志m,根据您的链接m modifier: multi-line. Causes ^ and $ to match the begin/end of each line (not only begin/end of string)【参考方案2】:

根据您的语言,只需在管道上拆分并获取最后一个元素。无需为此使用正则表达式!

在 C#.NET 中:

var myString = "lwiod[2469]: S-1-5-21-2071757552-4033313730-2397045981-3628|0xC94F000|LOGON|STATUS_SUCCESS|10.10.19.10|10.10.42.40|COMPANY\USERNAME"
var login = myString.Split('|').Last();
if (login.contains("\"))

    login = login.Split('\').Last();

【讨论】:

不幸的是,我没有能力强加任何基于语言的逻辑。这些是发送到商业 SIEM 的系统日志条目,所以我只有一个正则表达式,并且只有一个正则表达式来完成我需要的。我还需要捕获字段 1-6 啊,听起来很悲伤。 :(【参考方案3】:

这将为您提供所需的所有字段。要删除公司,您必须添加更复杂的正则表达式,我现在开始编写。

您可以使用组将其捕获到反向引用中:

: ([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|(?:COMPANY\\)?([^|@]+)(?:@COMPANY)?$

这将使您的所有组进入反向引用 1-7。

backreference \7 是您没有公司的用户名。

【讨论】:

我同意你的观点! :)

以上是关于条件正则表达式,如何提取匹配的子集?的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式查找单词的最佳匹配子集

R 模式匹配与正则表达式的子集 data.table

正则表达式与 C# 中的 OR 条件最长匹配

正则表达式说明

如何使用 Vim 提取匹配正则表达式的文本?

excel VBA匹配,这是我写的正则表达式: