Не удается встроить заменить с помощью re.sub и io.StringIO в Python
Я написал этот метод для того, чтобы заменить текст в строке. Он печатает правильный текст, так как я хочу, чтобы он был заменен, но он не обновляет эти изменения в файле. Я новичок в Python, не могли бы вы помочь мне, где я делаю ошибку?
def regFind(regx, sub_text, file_name):
c_file = io.StringIO(file_name)
for line in c_file:
match = regx.search(line)
if match:
replaced_line = re.sub(regx, sub_text, line)
line = replaced_line
#print(line)
yield line
regx = re.compile(r'^MYTEXT')
sub_text = 'NewText'
a_file = open('file.txt').read()
for line in regFind(regex, sub_text, a_file):
print(line)
3 ответа
В стандартной библиотеке есть модуль, помогающий редактировать файлы "на месте" - fileinput. Фактически, он не редактирует файлы на месте, вместо этого он записывает выходные данные во временный файл, а затем переименовывает временный файл в исходный файл. Это создает впечатление, что файл был отредактирован на месте, если все идет хорошо. Если возникает исключение или программа останавливается до шага переименования, то исходный файл остается без изменений.
import fileinput
import sys
import re
screen = sys.stdout
def regFind(regx, sub_text, filename):
for line in fileinput.input([filename],
inplace=True,
backup='.bak' # creates a backup of the original file
):
match = regx.search(line)
if match:
line = regx.sub(sub_text, line)
sys.stdout.write(line)
yield line
# regex = re.compile(r'foo')
for line in regFind(regex, sub_text, 'file.txt'):
screen.write(line+'\n')
fileinput
переадресовывает sys.stdout
записывать во временный файл, а не в консоль. Поэтому для печати на консоль я сохранил оригинал sys.stdout
к переменной screen
и использовать screen.write
вместо print
,
Редактировать Ваш код не работает, потому что вы не пишете эти строки в текстовые файлы.
Также, если вы хотите заменить текст в файле, вам необходимо скопировать содержимое файла, открыть файл в режиме записи (который очищает весь файл), а затем записать измененный контент в файл:
def regFindAndReplace(regx, sub_text, fileName):
textFile = open(fileName)
fileContent = textFile.readlines()
textFile.close()
writeFile = open(fileName,'w')
for line in fileContent:
# strip removes newline character if line has one, you probably wont need it but it does not do harm either
line = line.strip()
match = regx.search(line)
if match:
replaced_line = re.sub(regx, sub_text, line)
line = replaced_line
#print(line)
writeFile.write(line+'\n')
#'\n' is way to create newline character because stripped line has it no longer
writeFile.close()
f = 'MyFile.txt'
regFindAndReplace(regex, sub_text, f)
Вам нужно явно записать изменения в файл. Например, открыть другой файл в режиме записи ('w'
) и использовать .write
способ поместить данные на диск:
def regFind(regx, sub_text, a_file):
for line in a_file:
match = regx.search(line)
if match:
replaced_line = re.sub(regx, sub_text, line)
line = replaced_line
#print(line)
yield line
f = open('file.txt')
out = open('result.txt', 'w')
for line in regFind(regex, sub_text, f):
out.write(line)
(Я также удалил ненужные StringIO
и перестал загружать весь файл в память .read()
)
PS Причина, по которой я пишу в другой файл, в том, что это безопаснее. Можно изменить файл на месте. Но вы можете потерять данные, если не будете достаточно осторожны.