Python逐行处理文件时如何修改匹配关键字对应的上一行
JTE v2模板转换Python实现方案
问题描述
需要通过Python脚本将旧版JTE模板转换为JTE v2格式,核心逻辑为:遍历文件内容时,识别到值为true的merge或override配置行,将对应注解添加到上一级代码块定义行的开头,同时删除当前的配置行。
原始模板内容
libraries { merge = true nexus { merge = true } sonarqube { merge = true } } git { merge = true checkout { override = true shallow = false } }
目标转换结果
@merge libraries { @merge nexus { } @merge sonarqube { } } @merge git { @override checkout { shallow = false } }
现存问题
初始实现仅完成基础文件读写,逐行直接写入输出文件的模式下,无法回溯修改已经写入的上一行内容,初始代码如下:
a_file = open("jenkins.groovy", "r") lines = a_file.readlines() a_file.close() new_file = open("jenkins_patched.groovy", "w") for line in lines: if line.strip("\n") != "merge" or line.strip("\n") != "override": new_file.write(line) new_file.close()
解决方法
不要逐行直接写入文件,先通过列表维护内存级的输出缓存,所有处理后的行暂存到列表中,待全部内容处理完成后再统一写入文件。遇到注解配置行时,直接修改列表中对应上一行的内容即可,无需操作文件指针回溯。
完整实现代码
import re # 读取原始模板文件 with open("jenkins.groovy", "r", encoding="utf-8") as f: lines = f.readlines() output_lines = [] # 匹配merge/override配置行的正则规则 anno_pattern = re.compile(r'^\s*(merge|override)\s*=\s*true\s*$') for line in lines: match_res = anno_pattern.match(line) if match_res: # 提取注解名称 annotation = match_res.group(1) # 提取当前行缩进,保证注解和块层级对齐 indent_length = len(line) - len(line.lstrip()) indent = ' ' * indent_length # 回溯找到最近的非空行(即对应的块定义行) target_idx = len(output_lines) - 1 while target_idx >= 0 and output_lines[target_idx].strip() == '': target_idx -= 1 # 给块定义行添加注解 if target_idx >= 0: block_content = output_lines[target_idx].lstrip() output_lines[target_idx] = f"{indent}@{annotation} {block_content}" # 跳过当前配置行,不加入输出列表 continue # 普通行直接加入输出缓存 output_lines.append(line) # 写入转换后的结果文件 with open("jenkins_patched.groovy", "w", encoding="utf-8") as f: f.writelines(output_lines)
逻辑说明
- 使用内存列表暂存输出内容,支持任意位置的行修改,从根本上解决逐行写入无法回溯修改上一行的问题
- 自动识别配置行的缩进值,保证转换后的注解和代码块层级完全对齐
- 兼容代码块与配置行之间存在空行的边界场景,可自动定位到对应的块定义行
- 正则匹配兼容行内多余空格的不规范写法,识别准确率更高
内容的提问来源于stack exchange,提问作者Mr. E
相关产品推荐
相关产品推荐

