Замена текста в одном и том же файле в цикле
Всем привет!
Есть следующая задачка. У меня есть файл, где имеется следующий текст:
`<!-- replace text here-->`
...
`<!-- replace text here-->`
...
`<!-- replace text here-->`
...
`<!-- replace text here-->`
...
`<!-- replace text here-->`
Я хочу с помощью цикла заменить эти значения на следующее:
`<!-- replace text here 0-->`
...
`<!-- replace text here 1-->`
...
`<!-- replace text here 2-->`
...
`<!-- replace text here 3-->`
...
`<!-- replace text here 4-->`
Где цифры - номер цикла. Для этого я написал следующий код:
for r in range (5):
with open(path_to_html, "r+") as f:
contents = f.read()
contents = re.sub(r'<!-- replace text here-->', '<!-- replace text here '+str(r)+'-->', contents)
f.write(contents)
f.truncate()
f.close()
Но по каким-то неведомым мне причинам я получаю следующий результат:
`<!-- replace text here 0-->`
...
`<!-- replace text here 0-->`
...
`<!-- replace text here 0-->`
...
`<!-- replace text here 0-->`
...
`<!-- replace text here 0-->`
Подскажите, пожалуйста, что я делаю не так?
Ответы (3 шт):
Можно так:
with open(path_to_html, "r") as f:
contents = f.read()
with open(path_to_html, "w") as f:
for r in range(5):
contents = re.sub(r'<!-- replace text here-->', '<!-- replace text here '+str(r)+'-->', contents, count=1)
f.write(contents)
f.truncate()
Почему по неведомым причинам?
На нулевой итерации у вас данная подстрока <!-- replace text here--> заменяется на <!-- replace text here 0--> во всех случаях.
На первой итерации у вас уже нет подстроки со значением <!-- replace text here--> в файле, поэтому ничего не меняется и не происходит. И так далее со всеми итерациями дальше.
Что можно сделать?
Поскольку существует метод replace для строк из коробки, я бы его и использовал, поскольку функционала достаточно для решения подобной задачи
for r in range (5):
with open(path_to_html, "r+") as f:
contents = f.read()
contents = contents.replace(r'<!-- replace text here-->', '<!-- replace text here '+str(r)+'-->', 1)
f.write(contents)
f.truncate()
f.close()
Далее, я бы пересмотрел логику, чтобы 5 раз не открывать один и тот же файл, а работать один раз с прочитаными данными и один раз записывать, после того как данные были изменены нужным образом
Метод replace(old, new, count), принимает 2 обязательных параметра (old, new) и один опциональный (count). В count мы передаем количество вхождений , которые нам необходимо заменить. Вам нужно менять только одно вхождение за одну итерацию, поэтому ставите еденичку и радуетесь результату
Присоединяюсь к замечанию Дмитрия - не гоже пять раз подряд открывать и закрывать файл. А если это будет 500 раз и более?
Ещё странным выглядит помещать f.truncate() после f.write(contents). Это не приведет к перезаписи файла. Новый текст будет добавлен в конец файла.
Предлагаю свой вариант:
# Открываем файл только для чтения
# и быстро считываем содержимое в локальную переменную
with open(path_to_html, 'r') as f:
# для больших файлов не лучшая идея читать файл целиком в память
content = f.read()
# оператор with сам закроет файл автоматически
# далее работаем с текстом в локальной переменной - content
search_text = '<!-- replace text here-->'
r = 0
# если требуется ограничить замену конкретного числа строк (max_count), то пишем:
# while search_text in content and r <= max_count:
# пока существует искомая фраза, заменяем текст (по одной итерации) на новый с очередным счетчиком
while search_text in content:
content = content.replace(search_text, '<!-- replace text here '+str(r)+'-->', 1)
r += 1
# снова открываем файл, но уже только для записи и обновляем весь файл целиком
with open(path_to_html, 'w') as f:
f.write(content)
Плюс предложенного варианта: Операции с файлом ограничены двумя короткими операциями. Во время работы "тяжелого" поиска текста, файл остается закрытым.
Можно доработать для работы с большими файлами - построчное чтение.
Если переменную search_text заменить списком строк и доработать цикл while, то возможно искать любое сочетание текста.