Python: удалить строки, кроме определенных критериев

Я пытаюсь удалить строки из файла, используя определенные критерии. Сценарий, который у меня есть, кажется, работает, но мне нужно добавить ко многим операторам Or. Есть ли способ создать переменную, которая содержит все критерии, которые я хотел бы удалить из файлов? ?

Пример кода

with open("AW.txt", "r+", encoding='utf-8') as f:
    new_f = f.readlines()
    f.seek(0)
    for line in new_f:
        if "PPL"not in line.split() or "PPLX"not in line.split() or "PPLC"not in line.split():
            f.write(line)
    f.truncate()

Я больше думал таким образом, но это не работает, когда я добавляю несколько критериев

output = []
with open('AW.txt', 'r+', encoding='utf-8') as f:
    lines = f.readlines()
    criteria = 'PPL'
    output =[line for line in lines if criteria not in line]

f.writelines(output)

С Уважением


person DGRL    schedule 29.08.2019    source источник
comment
Может быть, использовать grep или sed, и это можно сделать в одну строку? grep -v "PPL[X|C]*" file.txt работает?   -  person Guru    schedule 29.08.2019
comment
альтернативой sed будет sed -E -i -e "/PPL(X|C)?/d" AW.txt   -  person yabhishek    schedule 29.08.2019


Ответы (3)


arrow_upward
0
arrow_downward

Вы можете использовать регулярные выражения, чтобы уменьшить количество операторов и проверок в коде. Если у вас есть список критериев, которые могут быть динамическими, назовем список критериев crit_list, тогда код будет выглядеть так:

import re
with open("AW.txt", "r+", encoding='utf-8') as f:
    new_f = f.readlines()
    crit_list = ['PPL', 'PPLC', 'PPLX']    # Can use any number of criterions
    obj = re.compile(r'%s' % ('|'.join(crit_list)))
    out_lines = [line for line in new_f if not obj.search(line)]
    f.truncate(0)
    f.seek(0)
    f.writelines(out_lines)

Использование regex делает его отличным от того, как опубликовал OP. Позвольте мне объяснить две строки, содержащие регулярное выражение:

obj = re.compile(r'%s' % ('|'.join(crit_list)))

Эта строка создает объект регулярного выражения с регулярным выражением 'PPL|PPLX|PPLC', что означает match at least one of these strings в данной строке, что можно рассматривать как замену использования в коде столько or, сколько есть критериев.

out_lines = [line for line in new_f if not obj.search(line)]

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

Надеюсь, это развеет ваши сомнения.

person yabhishek    schedule 29.08.2019
comment
Спасибо за это. Написано немного по-другому, но делает то, что нужно. - person DGRL; 29.08.2019
comment
@Unwanted Объяснил две неочевидные строки для вашего понимания, если вы не знакомы с регулярными выражениями. - person yabhishek; 29.08.2019
comment
Спасибо и вам, и @Dex за помощь в этом и желание немного изучить Python :-) - person DGRL; 30.08.2019

arrow_upward
0
arrow_downward

import re

output = []
with open('AW.txt', 'r+', encoding='utf-8') as f:
    lines = f.readlines()
    criteria = 'PPL'
    output = re.sub("^.*[Crit1|Crit2|Crit3].*","")

f.writelines(output)


Это удалит линии. но он не распечатает их в операторе writelines, ваш вопрос был немного нечетким, вы просили удалить строки, но затем пытались их записать, добавьте столько критериев, сколько хотите, вот так

person bain2236    schedule 29.08.2019

arrow_upward
0
arrow_downward

Вы можете сравнить каждый элемент списка с каждым критерием и получить только те элементы, которые соответствуют критериям. Затем просто получите все строки, которые соответствуют всем критериям.

Например, это можно сделать так (ОТРЕДАКТИРОВАННЫЙ КОД):

with open('AW.txt', 'r+') as f:
    lines = f.readlines()
    criterias = ["PPL","PPLX","PPLC"]
    conditioned_lines = [[line for criteria in criterias if criteria not in line] for line in lines]
    output = [criteria_lines[0] for criteria_lines in conditioned_lines if len(criteria_lines) == len(criterias)]
    f.truncate(0)
    f.seek(0)
    f.write(''.join(output))
person Arsal    schedule 29.08.2019
comment
я получаю эту ошибку в вашем коде ValueError: операция ввода-вывода в закрытом файле. Для всех остальных, извините за нечеткость, лол. Я имею в виду, что у меня есть текстовый файл с большим количеством строк. Указанные критерии - это те, которые необходимо удалить из файла. Все остальное, что не соответствует этим критериям, должно остаться. в файле С уважением - person DGRL; 29.08.2019
comment
Даже если файл был открыт, он добавлял содержимое вывода в файл, а не заменял содержимое файла содержимым списка вывода. Я изменил свой ответ, который удаляет строки из файла, содержащего слова критериев. - person yabhishek; 29.08.2019
comment
Спасибо. Ошибка была из-за того, что f.writelines(output) был из коробки (только вкладка, и ошибка исчезла. Скрипт, похоже, не удаляет строки и не добавляет их. Может ли это быть из-за того, что строки разделены табуляцией? Line.split может применяться здесь правильно? - person DGRL; 29.08.2019
comment
Пожалуйста, попробуйте код сейчас, я его отредактировал. Он заменит содержимое AW.txt обновленными строками. - person Arsal; 29.08.2019
comment
Как раз то, что мне было нужно Спасибо за помощь :-) Ценю это - person DGRL; 29.08.2019
comment
Вам не нужно явно закрывать файл, with менеджер контекста позаботится об этом. - person yabhishek; 29.08.2019
comment
@yabhishek да, верно, спасибо. Я отредактировал это. - person Arsal; 29.08.2019
comment
Могу я спросить вас еще 1 вещь, как я могу перевернуть этот сценарий? Я имею в виду, что теперь я отфильтровываю то, что мне не нужно. Но как я могу отфильтровать то, что хочу сохранить? Я думал об удалении не в строке [[строка для критериев в критериях, если критерии не в строке] для строки в строках] Но это не работает, лол - person DGRL; 29.08.2019
comment
Эта проверка неверна len(criteria_lines) == len(criterias), поскольку предполагает, что все критерии должны присутствовать в строке, чтобы сохранить эту строку. Однако @Unwanted хочет сохранить строку, если она соответствует хотя бы одному из критериев. Эта проверка приводит к тому, что output_list становится пустым. - person yabhishek; 29.08.2019
comment
@Unwanted Вы можете посмотреть мой ответ для своей цели и удалить not из строки, содержащей not obj.search(line), и это послужит вашей обратной цели. - person yabhishek; 29.08.2019
comment
@yabhishek Это может быть я, но я не могу найти строку not obj.search(line) в вашем коде. И единственное, чего нет в сценарии, находится в строке [[строка для критериев в критериях, если критерии не в строке] для строки в строках] Удаление этого приведет к тому, что выходной файл станет пустым, а удаление проверки приведет к сбою запуска. Позвольте мне попытаться понять это, поскольку я узнаю об этом, спасибо за толчок :-) - person DGRL; 29.08.2019
comment
Мой ответ другой. Вы имеете в виду ответ @Dex. Мой ответ - один из двух других ответов, и это раздел комментариев к ответу, на который вы ссылаетесь. Если вы публикуете вопрос, попробуйте просмотреть другие соответствующие ответы, так как вы можете получить лучшие ответы на свои вопросы, просмотрев все ответы. - person yabhishek; 29.08.2019
comment
Извинения @yabhishek - person DGRL; 29.08.2019