Алгоритм простой:
- Прочитать текст;
- Найти вхождение строки;
- Заменить;
- Записать.
Как это сделать правильно?
- Зачитывать побайтово, чтобы сэкономить память. Лучше поблочно, так быстрее;
- Искать в блоке начало вхождения строки, и сравнивать, добавляя блок если совпадение найдено;
- Если есть полное совпадение, то заменить фрагмент нужной строкой;
- Записывать в файл назначения поблочно.
Простой способ решения на python2 с зачитыванием текста в память и записью текста после замены.
nano replace_text.py
#!lineos='inline' hl_lines='1 3 10'
# -*- coding: utf8 -*-
# Существует множество способов сделать замену в тексте
# import this
import sys
def replace_text(source_file_name, destination_file_name, target_text, text_for_replace):
with open(source_file_name, 'r') as source:
source_text = source.read()
with open(destination_file_name, 'w') as destination:
destination.write(source_text.replace(target_text, text_for_replace))
if __name__ == "__main__":
if len(sys.argv)==5:
replace_text(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4])
else:
print '''run 'python replace.py' with arguments:
<source_file_name>
<destination_file_name>
<target_text>
<replace_text>'''
Для решения этой задачи можно использовать аккумулятор, и читать посимвольно в буфер python3:
#!lineos='inline' hl_lines='1 3 10'
import sys
''' Существует множество способов сделать замену в тексте
используется аккумулятор, память расходуется под буфер длиной в поисковую строку '''
def replace_text(source_file_name, destination_file_name, target_text, text_for_replace):
target_text_len = len(target_text)
target_text_bytes_len = len(target_text.encode('utf-8'))
def compare():
need_replace = False
compare_buffer = ''
while True:
buffer_character = (yield need_replace)
compare_buffer += buffer_character
if len(compare_buffer) < target_text_len:
continue
else:
compare_buffer = compare_buffer[-target_text_len:]
need_replace = compare_buffer == target_text
with open(destination_file_name, 'w') as destination, open(source_file_name, 'r') as source:
character = source.read(1)
# создаем аккумулятор
comparator = compare()
# инициализируем аккумулятор
next(comparator)
while character:
# добавляем по одному символу для заполнения буфера
need_replace_text = comparator.send(character)
if need_replace_text:
# последний отправленный в компаратор символ еще не записали
write_position = destination.tell()-target_text_bytes_len+len(character.encode('utf-8'))
destination.seek(write_position)
destination.write(text_for_replace)
else:
destination.write(character)
character = source.read(1)
if __name__ == "__main__":
if len(sys.argv) == 5:
replace_text(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
else:
print('''run 'python replace.py' with arguments:
<source_file_name>
<destination_file_name>
<target_text>
<replace_text>''')
comments powered by Disqus