繁体   English   中英

匹配在python中找到的字符串之后打印一些前面的行

[英]Print a number of previous lines after matching string found in line in python

我正在编写一个程序来解析一些日志文件。 如果行中有错误代码,我需要打印前25行进行分析。 我希望能够根据各个错误代码(而不是25行,15或35)用更多或更少的行重复这个概念。

with open(file, 'r') as input:
     for line in input:
         if "error code" in line: 
             #print previous 25 lines

我知道Bash中的等效命令是我需要的是grep "error code" -B 25 Filename | wc -1 grep "error code" -B 25 Filename | wc -1 我一般都是python和编程新手,我知道我需要一个for循环而且我已经尝试使用range函数来做这个但是我运气不好因为我不知道怎么做将范围实现到文件中

这是一个长度有限的collections.deque的完美用例:

from collections import deque

line_history = deque(maxlen=25)
with open(file) as input:
    for line in input:
        if "error code" in line: 
            print(*line_history, line, sep='')
            # Clear history so if two errors seen in close proximity, we don't
            # echo some lines twice
            line_history.clear()
        else:
            # When deque reaches 25 lines, will automatically evict oldest
            line_history.append(line)

完整解释我选择这种方法的原因(如果你不在乎,请跳过):

使用for / range ,这不能以良好/安全的方式解决,因为仅当将整个文件加载到内存中时,索引才有意义; 磁盘上的文件不知道行的开始和结束位置,因此你不能只是从头开始查询第1到356行的“第357行文件”。你要么最后重复读取文件,或将整个文件啜饮到内存中的序列(例如list / tuple )以使索引有意义。

对于一个日志文件,你必须假设它可能非常大(我经常处理多GB的日志文件),将它加载到内存中将耗尽主内存,因此啜饮是一个坏主意,并重新读取文件每次遇到错误都是从头开始几乎一样糟糕(它很慢,但我猜它可靠得慢?)。 基于deque的方法意味着您的峰值内存使用量基于文件中的27个最长行,而不是总文件大小。

除了内置插件之外什么都不是天真的解决方案可以简单到:

with open(file) as input:
    lines = tuple(input)  # Slurps all lines from file
for i, line in enumerate(lines):
    if "error code" in line:
        print(*lines[max(i-25, 0):i], line, sep='')

但就像我说的那样,这需要足够的内存来将你的整个日志文件同时保存在内存中,这是一件坏事。 当两个错误发生在近距离时它也重复行,因为与deque不同,你没有一个简单的方法来清空你最近的记忆; 您必须手动跟踪上次print的索引以限制切片。

请注意,即使这样,我也没有使用range ; range是一个拐杖很多人来自C背景依赖,但它通常是解决Python问题的错误方法。 需要索引的情况下(通常不需要),您通常也需要该值,因此基于enumerate的解决方案更优越; 大多数情况下,您根本不需要索引,因此直接迭代(或使用zip等配对迭代)是正确的解决方案。

尝试使用for循环和range函数进行基本编码,无需任何特殊库:

N = 25
with open(file, 'r') as f:
    lines = f.read().splitlines()
    for i, line in enumerate(lines):
        if "error code" in line: 
            j = i-N if i>N else 0
            for k in range(j,i):
                print(lines[k])

如果总行数小于25,则上面打印前25行或从第一行打印。

此外,最好避免将input用作变量项,因为它是Python中的关键字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM