首页 > 解决方案 > 正则表达式日志解析 - 如何在一个事件中开始解析行并在另一个事件中停止解析行?

问题描述

我有一个日志文件,每行跟踪几个游戏事件,但这也包括在“官方”游戏时间之外发生的事件(即赛前等)。我有预定义的正则表达式模式,可以读取和解析每个事件,并聚合这些统计数据,尽管这包括在正式回合之前和之后发生的多余统计数据。

我的统计数据聚合目前很好,我目前正在努力解析一系列两个事件。没有明确的“比赛开始”事件,但有一个“回合开始”事件,该事件对比赛期间开始的一轮都计数。游戏结束更简单,因为“游戏结束”是一个记录的事件。

如果我能够读取“回合开始”事件和“游戏结束”事件,我将如何在“回合开始”的第一个实例开始读取文件中的行,并在游戏结束后完成读取行已触发?

eg:
line 37 | trigger "(Round_Start)"  <-- begin parsing here
...
line 192 | trigger "(Round_Start)"
...
line 304 | trigger "(Round_Start)"
...
line 486 | trigger "(Round_Start)"
...
line 594 | trigger "(Game_Over)"    <-- finish parsing here

请参阅下面的一些代码,这可能会有所帮助。

dmgEvent_P = re.compile(r'"([\w\s]+)<.*hurt "([\w\s]+)<.*\(dmg "(\d+)"')
hpEvent_P = re.compile(r'"([\w\s]+)<.*healed "([\w\s]+)<.*\(hp "(\d+)"')
roundStart_P = re.compile(r'trigger "(Round_Start)"')
gameOver_P = re.compile(r'trigger "(Game_Over)"')



matches = dmgEvent_P.finditer(contents)
    for match in matches:
        dealer = match.group(1)
        receiver = match.group(2)
        dmg = int(match.group(3))
        modifyDMG(dealer, receiver, dmg)
matches = healthEvent_P.finditer(contents)
    for match in matches:
        dealer = match.group(1)
        receiver = match.group(2)
        hp = int(match.group(3))
        modifyHP(dealer, receiver, hp)

还有其他游戏内事件正在被跟踪,但它们的功能非常相似。

就目前而言,我当前的代码目前通过每个正则表达式解析函数完全读取日志内容来解析所有事件,而不是逐行汇总。我希望能够在我上面定义的范围内共同解析这些行。

标签: pythonpython-3.xregex

解决方案


您可以匹配trigger "(Round_Start)"并读取所有不包含的行 trigger "(Game_Over)"

^.*?\btrigger "\(Round_Start\)".*(?:\n(?!.*\(Game_Over\)).*)*

正则表达式演示

如果 (Game_Over) 应该出现在行之后,您可以在捕获组中捕获它之前的行,然后匹配包含 (Game_Over) 的行

^(.*?\btrigger "\(Round_Start\)".*(?:\n(?!.*\(Game_Over\)).*)*)\n.*?\btrigger "\(Game_Over\)"

模式匹配

  • ^字符串的开始
  • (捕获组 1
    • .*?\btrigger "\(Round_Start\)".*匹配包含触发器“(Round_Start)”的整行
    • (?:非捕获组作为一个整体重复
      • \n(?!.*\(Game_Over\)).*匹配一个换行符,如果它不包含 (Game_Over) 则使用负前瞻匹配该行的其余部分。如果要排除更多行,可以使用(?!.*(?:\(Game_Over\)|another string)
    • )*关闭非捕获组并可选择重复
  • )关闭捕获组 1
  • \n.*?\btrigger "\(Game_Over\)"匹配换行符,并在该行匹配触发器“(Game_Over)”

正则表达式演示

注意转义括号\(\)或否则"(Round_Start)"将不匹配,并且只会(Round_Start)捕获捕获组中的文本。


推荐阅读