Попытка пропустить строки, соответствующие регулярному выражению, при записи в файл, но в новом файле есть дополнительные новые строки

Это ответвление на вопрос, который я задал здесь.

Я пытаюсь настроить метод, который может редактировать текстовые файлы на основе входного словаря. Это то, что у меня есть до сих пор:

info = {'#check here 1':{'action':'read'}, '#check here 2':{'action':'delete'}}

search_pattern = re.compile(r'.*(#.+)')        

    with open(input_file_name, "r") as old_file, open(output_file_name, "w+") as new_file:
        lines = old_file.readlines()

        for line in lines:
            edit_point = search_pattern.search(line)
            if edit_point:
                result = edit_point.group(1)
                if result in info and info[result]["action"] == "insert":#insert new lines to file
                    print("insert information to file")
                    new_file.write("\n".join([str(n) for n in info[result]["new_lines"]]))
                    new_file.write(result)
                elif result in info and info[result]["action"] == "delete":#skip lines with delete action
                    print("found deletion point. skipping line")
                else:#write to file any line with a comment that is not in info
                    new_file.write(line)
            else:#write lines that do not match regex for (#.*)
                new_file.write(line)

По сути, когда вы отправляете словарь, программа будет перебирать файл в поисках комментариев. Если комментарий есть в словаре, он проверит соответствующее действие. Если действие заключается в вставке, оно запишет строки в файл. Если это удалить, он пропустит эту строку. Любая строка без комментария должна быть записана в новый файл.

Моя проблема в том, что когда я удаляю строку из файла, оказывается, что там, где они были раньше, появляются дополнительные новые строки. Например, если у меня есть список:

hello world

how are you #keep this
I'm fine #check here 2
whats up

Я ожидаю, что вывод будет:

hello world

how are you #keep this
whats up

Но вместо этого у меня есть пустая строка:

hello world

how are you #check here 2

whats up

Я подозреваю, что это мой последний оператор else, который записывает в файл любую строку, не совпадающую с edit_point, в данном случае новые строки. Однако я понимаю, что цикл for должен идти построчно и просто идти по этой строке. Может ли кто-нибудь сказать мне, что мне здесь не хватает?


person SVill    schedule 07.04.2020    source источник
comment
Ваш код, ваш входной текст и выходные тексты не совпадают. В вашем словаре info нет ключей '#keep this' или '#delete this', поэтому он всегда будет иметь значение False и перейти к оператору else, и в этом случае он должен просто распечатать весь файл.   -  person Grand Phuba    schedule 07.04.2020
comment
Я попробовал ваш код, и файл вернулся без изменений. Вы уверены, что код, который вы разместили, именно тот, который у вас есть?   -  person Wiktor Stribiżew    schedule 07.04.2020
comment
Код именно тот, что у меня есть. Единственная разница для файла заключается в том, что я поставил здесь #delete вместо #check здесь 2, чтобы описать ожидаемое поведение. Я обновил файл, чтобы отразить это.   -  person SVill    schedule 07.04.2020


Ответы (1)


Это выглядит немного запутанным, вы смешиваете логику чтения и записи с логикой обработки, что затрудняет отслеживание того, что происходит. Вместо этого попробуйте этот подход:

from enum import Enum
from typing import Dict, List


class Action(Enum):
    KEEP = "keep"
    REMOVE = "remove"


definition = {
    "#KEEP": {"action": Action.KEEP},
    "#REMOVE": {"action": Action.REMOVE},
}


def clean_comments(
    lines: List[str], definition: Dict[str, Dict[str, str]]
) -> List[str]:

    # Keep a list of the lines that should be in the output
    output: List[str] = []

    # Loop the lines
    for line in lines:

        # If any of the comments in the definition is found, process further
        if any([comment in line for comment in definition.keys()]):

            # Figure out what to do
            for comment, details in definition.items():
                if comment in line:

                    if details["action"] == Action.KEEP:
                        output.append(line)
                        break

                    elif details["action"] == Action.REMOVE:
                        break

        # Keep all other lines
        else:
            output.append(line)

    return output


# Your data here...
with open("test_input.txt", "r") as f:
    lines = f.readlines()

# Use the function to clean the text
clean_text = "".join(clean_comments(lines, definition))

# Show the output
print(clean_text)

# Write to file
with open("test.txt", "w") as f:
    f.write(clean_text)

Выход:

hello world

how are you #KEEP: This line will be kept in the output file
whats up
person Gijs Wobben    schedule 28.06.2021