Есть некий файл, состоящий из строк. Нужно удалить выборочно строки, начинающиеся с определенного набора символов при помощи python. Как это сделать?
Вот пример
ATOM 14ATOM 15ANISOU 15ATOM 16ANISOU 16нужно удалить все, что начинается с ANISOU
PythonLib
Питон для всех
question@mail.ru
·
01.01.1970 03:00
Есть некий файл, состоящий из строк. Нужно удалить выборочно строки, начинающиеся с определенного набора символов при помощи python. Как это сделать?
Вот пример
ATOM 14ATOM 15ANISOU 15ATOM 16ANISOU 16нужно удалить все, что начинается с ANISOU
answer@mail.ru
·
01.01.1970 03:00
Как удалить каждую вторую строку из файла на python?
, чтобы прозрачно создать временный файл, чтобы по месту изменения выполнить:
#!/usr/bin/env python3import fileinputimport oswith fileinput.FileInput(filename, inplace=True, backup='.bak') as file: for i, line in enumerate(file, start=1): if i & 1: # odd print(line, end='') # keep line (stdout is redirected to the file)os.unlink(filename + '.bak') # remove the backup on successЭтот for-цикл можно также записать, :
import sysfrom itertools import islicesys.stdout.writelines(islice(file, 0, None, 2)) # keep lines[::2]Если реализация .writelines() не пишет строки по мере поступления, а загружает их всех в память, то можно использовать явный for-цикл, чтобы по одной строке писать, не загружая весь файл в память.
Для небольшого файла полный код может использовать .readlines(), чтобы получить список строк (загрузить файл в память) и целиком перезаписать этот файл, рискуя потерять данные если ошибка возникнет:
with open(filename) as file: lines = file.readlines()[::2] # lines to keepwith open(filename, 'w') as file: file.writelines(lines)Для небольшого файла, заданного с командной строки или стандартного ввода (stdin), пренебрегая возможными ошибками, :
#!/usr/bin/env python3import fileinputfrom itertools import isliceprint("""".join(islice(fileinput.input(), 0, None, 2)), end='')это полный скрипт. Использование:
$ every-other-line file1 file2 >output_fileВ более общем случае, чтобы удалить строки по месту из файла, не создавая временный файл и не загружая всё содержимое в память, , но вероятно менее эффективное решение создают:
from itertools import islicewith open(filename, 'r+') as file: write_offset = file.tell() # where to write next for line in islice(iter(file.readline, ''), 0, None, 2): # keep lines[::2] read_offset = file.tell() # where to read next file.seek(write_offset) file.write(line) write_offset = file.tell() file.seek(read_offset) file.truncate(write_offset)Этот более сложный вариант работает и для файлов, которые как в оперативную память не помещаются так и для которых нет места, чтобы копию на диске создать.
нужно удалить все, что начинается с ANISOU
Можно адаптировать приведённые выше примеры кода:
import fileinputimport oswith fileinput.FileInput(filename, inplace=True, backup='.bak') as file: for line in file: if not line.startswith('ANISOU'): print(line, end='') # keep line (stdout is redirected to the file)os.unlink(filename + '.bak') # remove the backup on successМожно (к примеру, если в текущей директории не достаточно места для копии файла, можно явно другую директорию указать (на другом диске) и использовать , если необходимо):
#!/usr/bin/env python3from pathlib import Pathfrom tempfile import NamedTemporaryFilepath = Path(filename)with path.open() as file, \ NamedTemporaryFile('w', dir=str(path.parent), delete=False) as output_file: for line in file: if not line.startswith('ANISOU'): print(line, end='', file=output_file)Path(output_file.name).replace(path)Загрузив строки в память:
with open(filename) as file: lines = [line for line in file if not line.startswith('ANISOU')]with open(filename, 'w') as file: file.writelines(lines)Легко адаптировать к другим условиям, определив keep_line() предикат, к примеру:
with open(filename) as file: lines = list(filter(keep_line, file))with open(filename, 'w') as file: file.writelines(lines)где в данном случае:
def keep_line(line): retu not line.startswith('ANISOU')