繁体   English   中英

如何使用 Python 更改现有文本文件以在特定行之后添加新数据

[英]How do I alter an existing text file to add new data after a specific line using Python

所以我希望创建一个脚本来使用 Python 为游戏制作一个 mod。 该脚本需要将所有文件从一个目录复制到另一个目录,然后更改这些文件以在特定行之后添加新属性。 我遇到的问题是该游戏使用基于 txt 文件中 json 格式的自定义编码。 我知道如何完成大部分工作,但是,添加新数据并不是我能做的事情。

我的最终目标是能够对任何文件执行此操作,因此其他模组作者可以使用它将数据添加到他们的模组中,而无需手动执行。 我也想尝试让这个脚本做更高级的事情,但这是另一个可以等到我开始工作的目标。

示例数据:我需要添加的行是position_priority = ### ###将根据建筑物的功能(建筑物类别)而有所不同。

我需要更改的示例代码:

building_name_number = {
    base_build_time = 60
    base_cap_amount = 1
    
    category = pop_assembly
   
    <more code>
}

我需要将新数据放在building_name_number之后,但是这个确切的名称将是唯一的,唯一始终相同的是它将以building开头。 所以正则表达式是我一直在尝试使用的,但我从未处理过正则表达式,所以我无法让它工作。

我当前的代码:

if testingenabled:
    workingdir = R"E:/Illusives-Mods/Stellaris/Building Sorting"
    pattern = "^building_"
    Usortingindex = sortingindex["sorting_pop_assembly"]
    print(f"Testing Perameters: Index: {Usortingindex}, Version: {__VERSION__}, Working DIR: {workingdir}")
    # os.chdir(stellaris_buildings_path)
    os.chdir(workingdir)
    for file in os.listdir(workingdir):

        if fnmatch.fnmatch(file, "*.txt"):
            
            print("File found")

            with open(file, "r+", encoding="utf-8") as openfiledata:
                alllines = openfiledata.read()
                for line in alllines:
                    if line == re.match(r'(^building_)', line, re.M):
                        print("found match")
                        # print(f"{sorting_attrib}{Usortingindex}")
                        # print("position_priority = 200")
                        openfiledata.write("\n" + sorting_attrib + Usortingindex + "\n")

            break

这段代码我没有收到任何错误。 但它不起作用我正在使用 Python 3.9.6

编辑:此代码在脚本之前

    allow = {
        hidden_trigger = {
            OR = {
                owner = { is_ai = no }
                NAND = {
                    free_district_slots = 0
                    free_building_slots <= 1
                    free_housing <= 0
                    free_jobs <= 0
                }
            }
        }
    }

这是之后

        allow = {
            hidden_trigger = {
                OR = {
                    owner = {
                        is_ai = false
                    }
                    NAND = {
                        free_district_slots = 0
                        free_building_slots = {
                            value = 1
                            operand = <=
                        }
                        free_housing = {
                            value = 0
                            operand = <=
                        }
                        free_jobs = {
                            value = 0
                            operand = <=
                        }
                    }
                }
            }
        }

输出必须与输入相同,至少在运算符方面

如果您将其保留为 JSON,那么您可以将所有内容读入 Python(将 ti 作为字典),在字典中搜索和添加项目,然后写回 JSON 新字典。

text = '''{
"building_name_number": {
    "base_build_time": 60,
    "base_cap_amount": 1,
    "category": "pop_assembly"
},
"building_other": {}
}'''

import json

data = json.loads(text)

for key in data.keys():
    if key.startswith('building_'):
        data[key]["position_priority"] = 'some_value'
        
print(json.dumps(data, indent=4))

结果:

{
    "building_name_number": {
        "base_build_time": 60,
        "base_cap_amount": 1,
        "category": "pop_assembly",
        "position_priority": "some_value"
    },
    "building_other": {
        "position_priority": "some_value"
    }
}

我发现模块paradox-reader可以将此文件格式转换为 JSON 文件。

使用paradoxReader.py文件中的代码,我创建了可以将字符串转换为 Python 字典、添加一些值并转换为类似于原始文件的内容的示例。 但这可能需要在encode()中添加更多代码

import json
import re

def decode(data):#, no_json):

    data = re.sub(r'#.*', '', data) # Remove comments
    data = re.sub(r'(?<=^[^\"\n])*(?<=[0-9\.\-a-zA-Z])+(\s)(?=[0-9\.\-a-zA-Z])+(?=[^\"\n]*$)', '\n', data, flags=re.MULTILINE) # Seperate one line lists
    data = re.sub(r'[\t ]', '', data) # Remove tabs and spaces

    definitions = re.findall(r'(@\w+)=(.+)', data) # replace @variables with value

    if definitions:
        for definition in definitions:
            data = re.sub(r'^@.+', '', data, flags=re.MULTILINE)
            data = re.sub(definition[0], definition[1], data)

    data = re.sub(r'\n{2,}', '\n', data) # Remove excessive new lines
    data = re.sub(r'\n', '', data, count=1)  # Remove the first new line
    data = re.sub(r'{(?=\w)', '{\n', data) # reformat one-liners
    data = re.sub(r'(?<=\w)}', '\n}', data) # reformat one-liners
    data = re.sub(r'^[\w-]+(?=[\=\n><])', r'"\g<0>"', data, flags=re.MULTILINE)  # Add quotes around keys
    data = re.sub(r'([^><])=', r'\1:', data)  # Replace = with : but not >= or <=
    data = re.sub(r'(?<=:)(?!-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)(?!\".*\")[^{\n]+', r'"\g<0>"', data)  # Add quotes around string values
    data = re.sub(r':"yes"', ':true', data) # Replace yes with true
    data = re.sub(r':"no"', ':false', data)  # Replace no with false
    data = re.sub(r'([<>]=?)(.+)', r':{"value":\g<2>,"operand":"\g<1>"}', data) # Handle < > >= <=
    data = re.sub(r'(?<![:{])\n(?!}|$)', ',', data)  # Add commas
    data = re.sub(r'\s', '', data) # remove all white space
    data = re.sub(r'{(("[a-zA-Z_]+")+)}', r'[\g<1>]', data) # make lists
    data = re.sub(r'""', r'","', data) # Add commas to lists
    data = re.sub(r'{("\w+"(,"\w+")*)}', r'[\g<1>]', data)
    data = re.sub(r'((\"hsv\")({\d\.\d{1,3}(,\d\.\d{1,3}){2}})),', r'{\g<2>:\g<3>},', data) # fix hsv objects
    data = re.sub(r':{([^}{:]*)}', r':[\1]', data) # if there's no : between list elements need to replace {} with []
    data = re.sub(r'\[(\w+)\]', r'"\g<1>"', data)
    data = re.sub(r'\",:{', '":{', data) # Fix user_empire_designs
    data = '{' + data + '}'

    return json.loads(data)

def encode(data):
    text = json.dumps(data, indent=4)
    text = text[2:-2]
    text = text.replace('"', '').replace(':', ' =').replace(',', '')
    return text

# ----------

text = '''building_name_number = {
    base_build_time = 60
    base_cap_amount = 1
    
    category = pop_assembly
}'''

data = decode(text)
data['building_name_number']['new_item'] = 123

text = encode(data)
print(text)

结果:

    building_name_number = {
        base_build_time = 60
        base_cap_amount = 1
        category = pop_assembly
        new_item = 123
    }

暂无
暂无

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

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