gpt4 book ai didi

regex - Perl 正则表达式对带或不带引号的项目进行分组并忽略空格

转载 作者:行者123 更新时间:2023-12-03 10:58:03 27 4
gpt4 key购买 nike

我有一些数据库信息被提取到临时日志中。我需要编写一个正则表达式来解析它,以便将其输入分析程序。我需要按如下方式对每个“字段”进行分组:

  • YYYY-MM-DD HH:MM:SS
  • 设施
  • 严重性
  • 服务器
  • YYYY-MM-DD: HH:MM:SS
  • 时区
  • IP 地址
  • 旧电子邮件地址
  • 名字(**可以包含也可以不包含用引号括起来的几个词)
  • 姓氏(**可以包含也可以不包含用引号括起来的几个单词)
  • 帐号
  • 程序代码
  • UID
  • 电子邮件地址
  • 事件类型
  • 来源
  • 类别

我几乎有了正则表达式,但在对字段进行分组时遇到问题。特别是 FirstName 和 LastName。理想情况下,我希望将这些捕获到两个字段中(如果存在引号,则去掉引号),但将 FirstName 和 LastName 合并为一个也很好。

当前正则表达式的问题是,虽然它将 FirstName 和 LastName 分组到一个字段中(不理想但可以接受),但似乎有一个额外的字段捕获一个空格。

这是我试图到达那里的正则表达式:

^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+(\S+)\.(\S+)\s+(\S+)\s+(\d{4}-\d{2}-\d{2}:\s\d{2}:\d{2}:\d{2})\s+(.*?)\s+(.*?)\s+(.*?)\s+(?<!")(.*)(?!")\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)$

以下是一些示例事件:

2016-01-29 18:19:54 local1.info server.domain.com 2016-01-29: 11:19:54 MST UNKNOWN UNKNOWN FOO "BAR BAZ" UNKNOWN UNKNOWN UNKNOWN EMAIL@EXAMPLE.COM PROFILE_CHANGE ProfileChangeProcessor A
2016-01-29 18:20:25 local4.info server.domain.com 2016-01-29: 11:20:25 MST UNKNOWN UNKNOWN "F B" BAZ ABC12345 GP SOME_UID EMAIL@EXAMPLE.COM EVENT_FROM_SOME_PROCESS UNKNOWN UNKNOWN
2016-01-29 18:23:10 local1.info server.domain.com 2016-01-29: 11:23:10 MST UNKNOWN UNKNOWN FOO BAR UNKNOWN UNKNOWN UNKNOWN EMAIL@EXAMPLE.COM SOME_CHANGE ProfileChangeProcessor AP
2016-01-29 18:26:24 local1.info server.domain.com 2016-01-29: 11:26:24 MST UNKNOWN EMAIL@EXAMPLE.COM FOO "B'Baz" UNKNOWN UNKNOWN UNKNOWN SOME_CHANGE ProfileChangeProcessor O
2016-01-29 18:26:55 local1.info server.domain.com 2016-01-29: 11:26:55 MST UNKNOWN EMAIL@EXAMPLE.COM "FOO OR BAR" BAZ SXR12646 GP UNKNOWN SOME_CHANGE ProfileChangeProcessor M

这是我通过 Perl 内联表达式运行它时的输出:

$ cat foo.txt | perl -ne '/^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+(\S+)\.(\S+)\s+(\S+)\s+(\d{4}-\d{2}-\d{2}:\s\d{2}:\d{2}:\d{2})\s+(.*?)\s+(.*?)\s+(.*?)\s+(?<!")(.*)(?!")\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)\s+(.*)$/ && print "$1|$2|$3|$4|$5|$6|$7|$8|$9|$10|$11|$12|$13|$14|$15|$16|\n"' 

2016-01-29 18:19:54|local1|info|server.domain.com|2016-01-29: 11:19:54|MST|UNKNOWN|UNKNOWN|FOO "BAR BAZ"|UNKNOWN|UNKNOWN|UNKNOWN|EMAIL@EXAMPLE.COM|PROFILE_CHANGE|ProfileChangeProcessor|A|
2016-01-29 18:20:25|local4|info|server.domain.com|2016-01-29: 11:20:25|MST|UNKNOWN|UNKNOWN|"F B" BAZ|ABC12345|GP|SOME_UID|EMAIL@EXAMPLE.COM|EVENT_FROM_SOME_PROCESS|UNKNOWN|UNKNOWN|
2016-01-29 18:23:10|local1|info|server.domain.com|2016-01-29: 11:23:10|MST|UNKNOWN|UNKNOWN|FOO BAR|UNKNOWN|UNKNOWN|UNKNOWN|EMAIL@EXAMPLE.COM|SOME_CHANGE|ProfileChangeProcessor|AP|
2016-01-29 18:26:24|local1|info|server.domain.com|2016-01-29: 11:26:24|MST|UNKNOWN|EMAIL@EXAMPLE.COM|FOO "B'Baz"|UNKNOWN|UNKNOWN|UNKNOWN||SOME_CHANGE|ProfileChangeProcessor|O|
2016-01-29 18:26:55|local1|info|server.domain.com|2016-01-29: 11:26:55|MST|UNKNOWN|EMAIL@EXAMPLE.COM|"FOO OR BAR" BAZ|SXR12646|GP|UNKNOWN||SOME_CHANGE|ProfileChangeProcessor|M|

使用上述正则表达式时的当前问题在于最后两条记录。在第 13 组中,有一个空字段。我不确定如何解释这一点。如果我无法获得输出数据的字段,则无法将其正确加载到分析引擎中。总的来说,我正在寻找是否有更好的方法根据我概述的内容对字段进行分组,并确保不存在空格(或类似字符)的分组。

最佳答案

这是我要做的:

^\s*
# date
(?<date>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})
# facility.severity
\s(?<facility>\S+)\.(?<severity>\S+)
# server
\s(?<server>\S*)
# date
\s(?<otherDate>\d{4}-\d{2}-\d{2}:\s\d{2}:\d{2}:\d{2})
# time zone
\s(?<timeZone>\S*)
# ip address
\s(?<ip>\S*)
# legacy email address
\s(?<legacyEmailAddress>\S*)
# first name
\s(?|"(?<firstName>[^"\n]+)"|(?<firstName>\S*))
# last name
\s(?|"(?<lastName>[^"\n]+)"|(?<lastName>\S*))
# account number
\s(?<account>\S*)
# program code
\s(?<programCode>\S*)
# uid
\s(?<uid>\S*)
# email address
\s(?<emailAddress>\S*)
# event type
\s(?<eventType>\S*)
# source
\s(?<source>\S*)
# category
\s(?<category>\S*)
\s*$

Demo with your sample data

  • 首先,当你有这样的模式时,你必须使用x修饰符,以便您可以将空格放入表达式中
  • 然后,$13 是什么意思?无论如何?为您的捕获组命名,这样更好。
  • 因为您可以有空字段,所以我假设字段之间恰好 有一个空白分隔符。你不能真的绕过那个
  • 添加比 \S* 更具体的规则不会有什么坏处,但这取决于你
  • 至于名称,格式是:(?|"(?<name>[^"\n]+)"|(?<name>\S*))
    • (?| ... )branch reset group .它允许您在其每个备选方案中重复使用相同的捕获组编号或名称
    • "(?<name>[^"\n]+)"捕获引用的名称
    • (?<name>\S*)捕获一个不带引号的名称...只有其中一个可以匹配,它们将进入同一个捕获组。

关于regex - Perl 正则表达式对带或不带引号的项目进行分组并忽略空格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35099189/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com