[英]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.