如何使用Python在文本文件匹配到的指定行后插入新数据
游戏Mod批量配置修改Python脚本实现
核心需求对齐
- 执行流程:先将指定源目录全量文件复制到目标目录,再批量修改目录内类JSON语法的自定义txt格式游戏配置
- 修改规则:在所有
building_前缀的建筑定义行(格式为building_xxx = {)下一行插入position_priority = ###,###取值随建筑所属分类动态变化 - 约束条件:修改后原文件的运算符、缩进、代码结构必须和原始文件完全一致,不得改动原有内容
- 落地目标:脚本通用可复用,其他Mod作者可直接使用,无需手动逐文件修改配置
- 现存问题:Python 3.9.6环境下正则匹配逻辑存在问题,脚本运行无报错但无法完成预期插入操作
实现说明
之前正则匹配失效基本是两个原因:一是写正则时没有兼容行首缩进、等号两侧空格数不固定的写法,导致匹配不到目标行;二是用全量文本替换的方式处理文件,很容易破坏原有格式。逐行遍历处理是最稳妥的方案,完全不会改动原有内容的格式。
适配Python 3.9.6的可直接复用代码如下:
import os import re import shutil from pathlib import Path # -------------------------- 可配置项 -------------------------- # 源配置目录、目标输出目录 SOURCE_DIR = Path("替换为你的源目录绝对/相对路径") TARGET_DIR = Path("替换为你的目标输出目录路径") # 建筑分类对应优先级映射,按实际需求修改即可 CATEGORY_PRIORITY = { "residential": 10, "commercial": 20, "industrial": 30, "public_service": 40, "default": 50 } # 需要处理的配置文件后缀 CONFIG_SUFFIX = ".txt" # 建筑定义行匹配正则:兼容任意行首缩进、等号两侧任意数量空格的写法 BUILDING_LINE_MATCH = re.compile(r'^(\s*)building_([a-zA-Z0-9_]+)\s*=\s*\{\s*$') # 配置块内缩进,游戏配置常用4空格,如果用Tab就改成"\t" INNER_INDENT = " " # ------------------------------------------------------------- def get_priority(building_id: str) -> int: """根据建筑ID匹配对应分类优先级,无匹配项返回默认优先级""" for cate, prio in CATEGORY_PRIORITY.items(): if cate in building_id: return prio return CATEGORY_PRIORITY["default"] def process_single_file(file_path: Path): """逐行处理单个配置文件,仅做插入操作不修改原有任何内容""" processed_lines = [] with open(file_path, 'r', encoding='utf-8-sig') as f: origin_lines = f.readlines() for line in origin_lines: processed_lines.append(line) match_res = BUILDING_LINE_MATCH.match(line) if match_res: # 继承原行的基础缩进,插入行对齐块内其他属性 base_indent = match_res.group(1) building_tag = match_res.group(2) insert_line = f"{base_indent}{INNER_INDENT}position_priority = {get_priority(building_tag)}\n" processed_lines.append(insert_line) with open(file_path, 'w', encoding='utf-8') as f: f.writelines(processed_lines) if __name__ == "__main__": # 清空已存在的目标目录后全量复制源文件 if TARGET_DIR.exists(): shutil.rmtree(TARGET_DIR) shutil.copytree(SOURCE_DIR, TARGET_DIR) # 递归遍历目标目录下所有配置文件处理 for root, _, files in os.walk(TARGET_DIR): for file_name in files: if file_name.endswith(CONFIG_SUFFIX): process_single_file(Path(root) / file_name)
使用注意事项
- 代码里的正则已经兼容所有合法的建筑定义写法:不管行首有多少缩进、等号两侧有多少空格,只要是
building_xxx = {格式的行都能精准匹配,不会漏判误判 - 读取文件用
utf-8-sig编码是为了兼容部分游戏配置带BOM头的情况,避免出现乱码 - 优先级匹配逻辑可以按需修改,当前默认逻辑是建筑ID包含对应分类关键词就使用对应优先级,也可以改成精确匹配、前缀匹配等其他规则
- 脚本不会修改源目录的任何文件,所有修改都在目标目录的副本上执行,避免误操作损坏原配置
- 如果需要跳过部分文件或者部分建筑,直接在匹配逻辑里加判断条件即可
内容的提问来源于stack exchange,提问作者The Illusion
相关产品推荐
相关产品推荐

