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)


Вы можете использовать регулярные выражения, чтобы уменьшить количество операторов и проверок в коде. Если у вас есть список критериев, которые могут быть динамическими, назовем список критериев 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

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

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

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

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