【问题标题】:Python regex how to find a substring that starts with a given word and ends with either of two wordsPython正则表达式如何找到以给定单词开头并以两个单词中的任何一个结尾的子字符串
【发布时间】:2021-08-05 00:00:51
【问题描述】:

我正在解析一个日志文件并试图找到一个以给定模式(比如Start log )开头并以两种模式之一(比如exit code \d.took \d* seconds.)结束的子字符串,以较晚者为准。

我尝试了以下方法但没有成功:

block_regex1 = re.compile('Start log .*?(exit code \d.|took \d* seconds.)', re.DOTALL)
block_regex2 = re.compile('Start log .*? exit code \d.|Start log .*? took \d* seconds.)', re.DOTALL)

block_regex.findall(log)

示例日志文件:

Start log 1
doing stuff
Finished with exit code 1.
Start log 2
doing stuff
Finished with exit code 0.
log 2 took 12 seconds.
Start log 3
doing stuff
Finished with exit code 0.
log 3 took 10 seconds.
Start log 4
doing stuff
Finished with exit code 1.

使用上面的代码,它应该输出一个列表:

  • Start log 1 doing stuff Finished with exit code 1.
  • Start log 2 doing stuff Finished with exit code 0. log 2 took 12 seconds.
  • ...

最终,我想获取日志 ID、退出代码以及以秒为单位的时间(如果存在)。我想我可以使用组来实现这一点,但仍在研究它。

【问题讨论】:

    标签: python regex logging


    【解决方案1】:

    使用

    Start log (?:(?!Start log).)*(?:exit code \d+|took \d* seconds)\.
    

    proof简而言之:尽可能多地匹配从Start logexit codetook xxx second 的文本,而不允许Start log 介于两者之间。

    解释

    --------------------------------------------------------------------------------
      Start log                'Start log '
    --------------------------------------------------------------------------------
      (?:                      group, but do not capture (0 or more times
                               (matching the most amount possible)):
    --------------------------------------------------------------------------------
        (?!                      look ahead to see if there is not:
    --------------------------------------------------------------------------------
          Start log                'Start log'
    --------------------------------------------------------------------------------
        )                        end of look-ahead
    --------------------------------------------------------------------------------
        .                        any character except \n
    --------------------------------------------------------------------------------
      )*                       end of grouping
    --------------------------------------------------------------------------------
      (?:                      group, but do not capture:
    --------------------------------------------------------------------------------
        exit code                'exit code '
    --------------------------------------------------------------------------------
        \d+                      digits (0-9) (1 or more times (matching
                                 the most amount possible))
    --------------------------------------------------------------------------------
       |                        OR
    --------------------------------------------------------------------------------
        took                     'took '
    --------------------------------------------------------------------------------
        \d*                      digits (0-9) (0 or more times (matching
                                 the most amount possible))
    --------------------------------------------------------------------------------
         seconds                 ' seconds'
    --------------------------------------------------------------------------------
      )                        end of grouping
    --------------------------------------------------------------------------------
      \.                       '.'
    

    【讨论】:

    • 效果很好,解释也很棒,谢谢!您建议如何完成任务的第二部分(获取作业 ID、退出代码和时间)?
    • @Pierre this 怎么样?
    • 看起来很棒,谢谢!我还找到了一种直接使用您的正则表达式 like this 的方法 - 假设如果给定时间我们知道退出代码是什么(#success!)然后我们可以使用 finditer 提取每个信息和group(n)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    相关资源
    最近更新 更多