В файле есть определенная строка, ее сначала выводит цикл на экран, всю строку, а потом нужно бы ее изменить, т.е. удалить старое и написать на ней новое, как это делается?
-
Связанные вопросы: Замена файле слов, Python Заменить слово в файле – m9_psy Apr 15 '17 at 19:50
-
похожие подходы можно использовать как в вопросе: Каким образом удалить строчки выборочно? и How to search and replace text in a file using Python? – jfs Apr 15 '17 at 21:08
-
2Если вам дан исчерпывающий ответ, отметьте его как верный (галка напротив выбранного ответа). – Nicolas Chabanovsky Apr 17 '17 at 05:47
4 Answers
Замену можно сделать так:
with open ('test.txt', 'r') as f:
old_data = f.read()
new_data = old_data.replace('что_меняем', 'на_что_меняем')
with open ('test.txt', 'w') as f:
f.write(new_data)
- 590
-
-
1
path = pathlib.Path('test.txt'); path.write_text(path.read_text().replace('old', 'new'))– jfs Mar 19 '18 at 08:42
Открыть файл на чтение можно либо так
file = open('filename.txt', 'r')
firstline = file.readlines()[0].strip()
file.close()
Либо так:
with open('filename.txt', 'r') as f:
print('first line', f.readlines()[0].strip())
Преимущество второго способа в том, что вам не надо закрывать файл вручную. Конструкция withсделает это за вас после закрытия её блока.
Перезаписать файл можно же таким образом:
with open('filename.txt', 'r') as f1, open('filename1.txt', 'w') as f2:
f2.write(f1.read())
Но так как вы хотите писать файл с заменой строки, то вам нужно воспользоваться перебором по readlines() и либо регулярными выражениями, либо сравнением текущей строки с той, которую вы ищите (если у вас есть искомая строка, конечно) и её заменой.
Грубо говоря, вы можете сделать это как-то так:
with open('filename.txt', 'r') as f1, open('filename1.txt', 'w') as f2:
lines = f1.readlines()
for line in lines:
line = line.strip()
if line == 'искомая строка':
f2.write('новая строка\n')
else:
f2.write(line)
Также могут помочь функции startswith() и endswith(), если у вас есть только начало или конец от искомой строки. И помните про регистр!
Также можно не перебирать строки, а обратиться к строке по индексу, если вам известно какой у неё номер, и заменить её содержание.
И можно воспользоваться функцией replace(), как уже написал автор второго ответа, что сократит количество кода, но заменит абсолютно все вхождения. Чтобы этого избежать, при вызове функции можно указать максимальное число совершаемых замен: S.max(sub_in_str, to_change_str, max).
Также учитывайте, что replace() совершит замену даже если строка частично совпадает. То есть выполнив это:
'This is a simple example'.replace('is', 'was')
Мы получим Thwas was a simple example
Если длина новой строки не совпадает с длиной старой, то придётся переписать весь файл (начиная со строчки, которую вы хотите заменить) даже если вам надо заменить только одну строку в файле (за редкими исключениями). Связанный вопрос: Запись текстовой строки по нужному индексу в файл на языке Си?
Чтобы в случае ошибки сохранить оригинал или для больших файлов (когда всё содержимое в памяти не помещается), может использоваться временный файл куда новое содержимое пишется и в конце в случае успеха он переименовывается в исходное имя файла. Похожий подход использует стандартный модуль fileinput: исходный файл переименовывается (чтобы из него читать текущее содержимое), а стандартный вывод перенаправляется в указанный файл (простой print печатает прямо в файл):
#!/usr/bin/env python3
import fileinput
import os
with fileinput.FileInput('файл.txt', inplace=True, backup='.bak') as file:
for line in file:
line = line.rstrip() # remove trailing (invisible) space
print('новое' if line == 'старое' else line) # stdout is redirected to the file
os.unlink(filename + '.bak') # remove the backup on success
Можно самостоятельно явно временный файл создать:
#!/usr/bin/env python3
from pathlib import Path
from tempfile import NamedTemporaryFile
path = Path('файл.txt')
with path.open() as file,
NamedTemporaryFile('w', dir=str(path.parent), delete=False) as output_file:
for line in file:
line = line.rstrip()
print('новое' if line == 'старое' else line, file=output_file)
Path(output_file.name).replace(path) # replace the input file on success
Отличие в том, что оригинальное содержимое хранится в .bak файле в fileinput подходе, а в коде с NamedTemporaryFile исходный файл заменяется только в случае успеха (в отсутствие исключений).
Небольшой файл можно в память целиком загрузить, чтобы получить список строк, изменить нужные и целиком перезаписать этот файл, рискуя потерять данные, если ошибка возникнет при записи (аналогично коду в @stxdtm ответе):
#!/usr/bin/env python3
filename = 'файл.txt'
with open(filename) as file:
lines = ['новое\n' if line.rstrip() == 'старое' else line for line in file]
with open(filename, 'w') as file:
file.writelines(lines)
Подробнее представленные подходы можно по ссылкам в похожем ответе посмотреть.
Если длина новой строки совпадает с длиной старой (в байтах), то можно прямо по месту изменения делать, не переписывая другие части файла, к примеру, используя mmap модуль, который позволяет файл рассматривать и как файл (.readline(), etc), и как байтовую строку (.find(), можно применять регулярные выражения). Связанный вопрос: Python - How can I change bytes in a file.
Название переменных говорит само за себя, также подробные коменты. Работает на линуксе, возвращяет количество измененных строк.
import os, subprocess
def LineReplacement(File, FindThis, ReplaceByThis):
TemporaryFile = File + '.tmp' # создаём
os.system("touch %s" % TemporaryFile) # временный файл
result = 0 # счетчик измененных строк
with open(File, 'r') as f1, open(TemporaryFile, 'w') as f2:
lines = f1.readlines()
for line in lines:
line = line.strip()
if line == FindThis:
f2.write(ReplaceByThis + '\n') # меняем строку
result = result + 1 # инкрементирование счетчика измененных строк
else:
f2.write(line + '\n') # оставляем прежнюю
path = os.path.join(os.path.abspath(os.path.dirname(__file__)), File)
os.remove(path) # удаляем основной файл
os.system("mv %s %s" % (TemporaryFile, File)) # переименовываем временный в основной
File = input("имя файла: ")
FindThis = input("что менять: ")
ReplaceByThis = input("на что менять: ")
result = LineReplacement(File, FindThis, ReplaceByThis)
print("изменено ", result, " строк")