如何在Python中捕获正则表达式匹配结果上方的n行内容?
这是个很实用的需求,尤其是处理日志类文本的时候。下面我会结合你给出的日志示例,一步步教你怎么在Python里实现这个功能:
首先先把你提供的日志文本展示出来,方便参考:
[01112017 110228 359][1][INFO]> Get Cash Unit Info
[01112017 110228 400][1][INFO]> ---Cash Unit Info Ready True
[01112017 110228 698][1][INFO]> Cash Unit Info - 0 Value 01 REJC --- 0000 0000 0004 000 OK
[01112017 110228 699][1][INFO]> Cash Unit Info - 1 Value 02 RETR --- 0000 0000 0000 000 OK
[01112017 110228 700][1][INFO]> Cash Unit Info - 2 Value 03 BILL LKR 5000 1000 0999 001 OK
[01112017 110228 700][1][INFO]> Cash Unit Info - 3 Value 04 BILL LKR ...
步骤1:预处理日志文本,分割成行
首先把日志字符串按换行符分割成列表,这样每一行都是列表里的一个元素,方便我们通过索引快速定位:
log_text = """[01112017 110228 359][1][INFO]> Get Cash Unit Info [01112017 110228 400][1][INFO]> ---Cash Unit Info Ready True [01112017 110228 698][1][INFO]> Cash Unit Info - 0 Value 01 REJC --- 0000 0000 0004 000 OK [01112017 110228 699][1][INFO]> Cash Unit Info - 1 Value 02 RETR --- 0000 0000 0000 000 OK [01112017 110228 700][1][INFO]> Cash Unit Info - 2 Value 03 BILL LKR 5000 1000 0999 001 OK [01112017 110228 700][1][INFO]> Cash Unit Info - 3 Value 04 BILL LKR ...""" # 分割成行,同时过滤掉可能的空行 log_lines = [line.strip() for line in log_text.split('\n') if line.strip()]
步骤2:定义正则表达式和要捕获的上方行数n
假设你想匹配包含Cash Unit Info - \d+ Value \d+ BILL的纸币单元信息行,然后捕获每一个匹配行上方的2行内容。你可以根据自己的实际需求调整正则表达式和n的值:
import re # 正则表达式,匹配目标行(可根据需求修改) pattern = re.compile(r'Cash Unit Info - \d+ Value \d+ BILL') n = 2 # 要捕获的上方行数
步骤3:遍历行列表,找到匹配行并捕获上方n行
遍历每一行,用正则检查是否匹配。如果匹配,就根据当前行的索引,取前面的n行(注意处理索引小于n的边界情况,比如第一行匹配的话,只能取前面已有的所有行):
# 存储结果:每个元素是(匹配行, 上方n行列表) results = [] for idx, line in enumerate(log_lines): if pattern.search(line): # 计算起始索引:如果当前索引 >=n,就从idx-n开始;否则从0开始 start_idx = max(0, idx - n) # 获取上方n行(不包含当前匹配行) preceding_lines = log_lines[start_idx:idx] results.append( (line, preceding_lines) ) # 打印结果 for match_line, pre_lines in results: print(f"匹配到的行:{match_line}") print(f"上方{n}行内容:") for l in pre_lines: print(f" {l}") print("-" * 50)
运行结果示例
针对你的日志,运行后会输出:
匹配到的行:[01112017 110228 700][1][INFO]> Cash Unit Info - 2 Value 03 BILL LKR 5000 1000 0999 001 OK 上方2行内容: [01112017 110228 698][1][INFO]> Cash Unit Info - 0 Value 01 REJC --- 0000 0000 0004 000 OK [01112017 110228 699][1][INFO]> Cash Unit Info - 1 Value 02 RETR --- 0000 0000 0000 000 OK -------------------------------------------------- 匹配到的行:[01112017 110228 700][1][INFO]> Cash Unit Info - 3 Value 04 BILL LKR ... 上方2行内容: [01112017 110228 699][1][INFO]> Cash Unit Info - 1 Value 02 RETR --- 0000 0000 0000 000 OK [01112017 110228 700][1][INFO]> Cash Unit Info - 2 Value 03 BILL LKR 5000 1000 0999 001 OK --------------------------------------------------
额外实用提示
- 如果日志是从文件读取的,可以直接用
with open('logfile.txt', 'r') as f: log_lines = [line.strip() for line in f if line.strip()]来获取行列表。 - 可以根据需要调整正则表达式,比如精确匹配某个特定的单元ID,或者其他日志模式。
- 如果处理超大日志文件,为了节省内存,可以不用一次性读入所有行,而是维护一个长度为
n的滑动窗口迭代器,每遇到匹配行时,窗口内的内容就是上方n行。
内容的提问来源于stack exchange,提问作者Prasad Chanaka

