Блог Синявского
  • Разделы
  • Метки
  • Все статьи

Функция замены текста в файле

1

Алгоритм простой:

  1. Прочитать текст;
  2. Найти вхождение строки;
  3. Заменить;
  4. Записать.

Как это сделать правильно?

  1. Зачитывать побайтово, чтобы сэкономить память. Лучше поблочно, так быстрее;
  2. Искать в блоке начало вхождения строки, и сравнивать, добавляя блок если совпадение найдено;
  3. Если есть полное совпадение, то заменить фрагмент нужной строкой;
  4. Записывать в файл назначения поблочно.

Простой способ решения на 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

Опубликовано

17.03.2013

Обновление

05.05.2022

Категории

python

Тэги

  • example 16
  • python 30

Всегда на связи

  • Блог Синявского - Ничего не переносить на завтра, это тоже проблема с прокастинацией?
  • © Алексей Синявский, по лицензии CC BY-SA если не указано иное.
  • С использованием Pelican. Тема: Elegant от Talha Mansoor