在适合两种格式的文本文件中查找所有字符串

Find all strings in text file fitting either of two formats

所以我知道以前也有人问过类似的问题,但是我试过的每一种方法都不行...

这是一个问题:我有一个文本文件(它是一个日志文件),我正在分析它是否出现任何“app.task2”。以下是可能发生的 2 种情况(它们出现在文本文件中,与我的代码无关):

场景 1:

    Mar 23 10:28:24 dasd[116] <Notice>: app.task2.refresh:556A2D:[
    {name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.45}}
 ] sumScores:68.785000, denominator:96.410000, FinalDecision: Can Proceed FinalScore: 0.713463}

场景 2:

Mar 23 10:35:56 dasd[116] <Notice>: 'app.task2.refresh:C6C2FE' CurrentScore: 0.636967, ThresholdScore: 0.410015 DecisionToRun:1

我面临的问题是,我下面的当前代码在第一种情况下没有获取整个日志条目,它只提取日志中的第一行,而不是日志条目的其余部分,并且它似乎在换行转义符处停止,该换行符出现在“:[”.

之后

我的代码:

all = []
with open(path_to_log) as f:
    for line in f:
        if "app.task2" in line:
            all.append(line)
print all

如何获取第一种情况的完整日志条目?我尝试剥离转义字符,但没有成功。从这里我应该能够解析返回的结果列表以获得我真正需要的结果,但这会有所帮助!泰!

注意:我需要能够通过字符串“app.task2”找到这些类型的日志条目(然后将为我们提供场景 1 或场景 2)。所以这需要合并,就像我的例子一样......

在将行添加到 all 之前,检查它是否以 [ 结尾。如果是,请继续阅读并合并行,直到到达 ].

import re

all = []
with open(path_to_log) as f:
    for line in f:
        if "app.task2" in line:
            if re.search(r'\[\s*$', line): # start of multiline log message
                for line2 in f:
                    line += line2
                    if re.search(r'^\s*\]', line2): # end of multiline log message
                        break
            all.append(line)
print(all)

您正在逐行遍历每一行,这就是为什么您在场景 1 中只得到第一行的原因。

要么你可以像这样添加一个计数器:

all = []
count = -1
with open(path_to_log) as f:
    for line in f:
        if count > 0:
           all.append(line)
           if count == 1:
             tmp = all[-count:]
             del all[-count:]
             all.append("\n".join(tmp))
           count -= 1
           continue
        if "app.task2" in line:
            all.append(line)
            if line.endswith('[\n'):
              count = 3
print all

在这种情况下,我认为 Barmar 解决方案同样有效。

或者您可以(最好)在存储日志文件时在每个日志条目之间使用一些不同的分隔符,并通过该分隔符拆分日志文件。

我喜欢@Barmar 在同一文件对象上使用嵌套循环的解决方案,并且将来可能会使用该技术。但是在看到之前我会用一个循环来完成它,这可能会或可能不会更具可读性:

all = []
keep = False

for line in open(path_to_log,"rt"):
    if "app.task2" in line:
        all.append(line)
        keep = line.rstrip().endswith("[")
    elif keep:
        all.append(line)
        keep = not line.lstrip().startswith("]")

print (all)

或者,您可以使用以下方法更好地打印它:

print(*all,sep='\n')