【问题标题】:python regex conditional substring extractionpython 正则表达式条件子字符串提取
【发布时间】:2012-08-28 05:45:57
【问题描述】:

我提出这个问题是因为我原来的问题似乎需要一个新的方向:my original question

我想创建一个正则表达式,可以从以下类型的日志条目中提取 STATIC MESSAGE 和 DYNAMIC MESSAGE:

/long/file/name/with.dots.and.extension:Jan 01 12:00:00 TYPE Static 消息;动态消息

/long/file/name/with.dots.and.extension:Jan 01 12:00:00 MODULE.NAME TYPE THREAD.OR.CONNECTION.INFORMATION 静态消息;动态消息

一种日志条目类型具有简单的结构:

file:date TYPE STATIC;DYNAMIC

另外一个在尝试用正则解析的时候就没那么简单了:

file:date MODULE.NAME TYPE CONNECTION.OR.THREAD STATIC;DYNAMIC

MODULE.NAMECONNECTION.OR.THREAD 要么存在要么不存在。

到目前为止,我适用于第一种日志条目的正则表达式是:

(?:.*?):(?:\w{3} \d{1,2} \d{1,2}:\d{1,2}:\d{1,2})(?:\s+?)(?:[\S|\.]*?(?:\s*?))?(?:(?:TYPE1)|(?:TYPE2)|(?:TYPE3))(?:\s+?)(?:\S+?(?:\s+?))?(.+){1}(?:;(.+)){1}

但每当我进入第二种类型的条目时,我也会将 CONNECTION.OR.THREAD 作为我的第一个捕获组的一部分。

我希望找到一种使用前瞻或后视功能的方法,以便我可以捕获STATICDYNAMIC,如果有MODULE.NAME,则忽略CONNECTION.OR.THREAD 部分?

我希望这个问题很清楚,如果看起来有点黯淡,请参考我的原作。谢谢。

编辑: 进行澄清。日志的每一行都不同,每一行都以文件路径开头,然后是:,然后是日期,格式如下:MMM DD HH:MM:SS,然后变得很棘手,要么是MODULE.NAME,它会有所不同,然后由同样变化的TYPE,然后是变化的CONNECTION.OR.THREAD,或者只有TYPE。之后是STATIC MESSAGE,然后是;,然后是DYNAMIC MESSAGE,静态和动态消息都不同,STATIC 一词的使用仅仅是因为错误可能是例如“无法连接到服务器; server1.com”,因此错误的静态部分是“无法连接到服务器”,而动态部分是“server1.com”

【问题讨论】:

  • 您需要明确日志行的哪些部分是逐行变化的内容的占位符,哪些部分是真正静态的。对于可能发生变化的部分,说明可能性有限的列表也会有所帮助。
  • @MartijnPieters 我已经进行了编辑,希望它能解决问题。
  • “静态”是什么意思?是固定字符串/固定字符串列表吗?
  • @J.F.Sebastian 我在我的编辑中解释了它:“静态”消息有点令人困惑,假装它说“part1;part2”
  • @InbarRose:每次都能使用工具而不用射中自己的脚并不等于和他们相处得很好......

标签: python regex logging python-2.6


【解决方案1】:

目前我已经制作了这个庞大的正则表达式:

(?:(?:.*?):(?:\w{3}(?: \d{1,2}){2}(?::\d{1,2}){2}))(?:\s+?)(?:(?:(?:(?:TYPE1)|(?:(?:TYPE1)|(?:TYPE3))(?:\s+?)(?:(.+){1};(.+){1}))|(?:\S+(?:\.\S+)+)(?:\s+?)(?:(?:TYPE1)|(?:TYPE1)|(?:TYPE3))(?:\s+?)(?:\S+(?:\.\S+)+)(?:\s+?)(?:(.+){1};(.+){1})))

我会把它分成几部分:

文件/日期 + 空格:

(?:(?:.*?):(?:\w{3}(?: \d{1,2}){2}(?::\d{1,2}){2}))(?:\s+?)

然后是:

简单:(静态类型;动态)

(?:(?:(?:TYPE1)|(?:TYPE1)|(?:TYPE3))(?:\s+?)(?:(.+){1};(.+){1}))

或复杂:(MODULE.NAME TYPE CONNECTION.OR.THREAD STATIC;DYNAMIC)

(:?(?:\S+(?:\.\S+)+)(?:\s+?)(?:(?:TYPE1)|(?:TYPE1)|(?:TYPE3))(?:\s+?)(?:\S+(?:\.\S+)+)(?:\s+?)(?:(.+){1};(.+){1}))

它成功了。但它很大,我认为它可以改进。所以请如果有人可以改进它,请做。

编辑:

虽然有问题。因为现在有 4 个捕获组。所以我无法提前知道我是否必须查看捕获的 [0:1] 或捕获的 [2:3] 以获得我的结果。任何人都有办法做到这一点,如果我有东西,我就不必每次都检查?或者可能是一种从结果中消除空捕获组的方法,或者可能只从结果列表中获取非空结果?某物?我的大脑被炸了。

EDIT2:

正如@martijn pieters 建议的那样,我删除了无关的分组,这是我当前的正则表达式:

.*?:\w{3}(?: \d{1,2}){2}(?::\d{2}){2}\s+?(?:(?:(?:TYPE1|TYPE2|TYPE3)\s+?(.+){1};(.+){1})|(?:\S+(‌​?:\.\S+)+\s+?(?:TYPE1|TYPE2|TYPE3)\s+?\S+(?:\.\S+)+\s+?(.+){1};(.+){1}))

效果很好。我担心(?:TYPE1|TYPE2|TYPE3) 被错误解释为TYPE(1|T)YPE(2|T)YPE3 任何见解将不胜感激。

另外,如何最好地解析我的结果 - 看到我将获得 4 个项目的列表,其中前 2 个或第二个 2 为空,另一个具有我的静态/动态结果。

EDIT3:

好的,我已经做了一个混合解决方案。我重新制作了我的正则表达式:

.*?:\w{3}(?: \d{1,2}){2}(?::\d{2}){2}\s+?(?:(?:(?:TYPE1|TYPE2|TYPE3))|(?:\S+(?:\.\S+)+\s+?(?:TYPE1|TYPE2|TYPE3)\s+?\S+(?:\.\S+)+))\s+(.*)

我现在只有 1 个捕获组,即 STATIC;DYNAMIC 部分。一旦我得到这个,我就会做我以前做的事情(见我的previous question

for item in captured:
    parts = item.split(";")
    static = parts[0]
    dynamic = ";".join(parts[1:])

这是我的解决方案。感谢@Martijn Pieters,特别是您的帮助。我希望这可以帮助将来的人。

【讨论】:

  • 第一;尝试稍微减少组,您似乎有不需要它们的冗余组(例如(?:.*?) 不需要组)。其次,使用(?P<groupname>..) 命名,这样你就可以得到一个字典结果,更容易使用。请参阅pastie.org/private/iyfwswt3stmvur25v9vu5w 了解我们用于解析来自 Web 服务器的日志行的示例。
  • @MartijnPieters 如果我给 2 个捕获组提供相同的名称,会发生什么?例如,如果我将 名称分配给捕获静态的两个组,并且知道它们是互斥的,因为它们位于 | 的任一侧,会发生什么?
  • 那会失败,你不能为两个组指定相同的名称。
  • @MartijnPieters 当事物分组时,我更容易查看正则表达式,如果分组较少,它会提高效率吗?即使他们是非捕获组?除了简单地遍历它们并检查它们的长度之外,有没有更好的方法从我的捕获列表中删除空结果?
  • 我链接的示例向您展示了提高可读性的不同方法;我发现你的模式目前非常难以理解。 (?:..) 组确实对正则表达式有意义,我不知道引擎是否将这些组识别为对匹配没有意义并将它们排除在外。为了安全起见,您应该只在确实需要分组(例如指定重复的复合组或| 选择分组)时使用它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多