Как заменить (обновить) текст в строке строки за строкой
Я пытаюсь заменить текст в текстовом файле, читая каждую строку, тестируя его, а затем записывая, если его нужно обновить. Я НЕ хочу сохранять как новый файл, так как мой script уже сначала выполняет резервное копирование файлов и работает с резервными копиями.
Вот что у меня есть до сих пор... Я получаю fpath из os.walk(), и я гарантирую, что var pathmatch возвращается правильно:
fpath = os.path.join(thisdir, filename)
with open(fpath, 'r+') as f:
for line in f.readlines():
if '<a href="' in line:
for test in filelist:
pathmatch = file_match(line, test)
if pathmatch is not None:
repstring = filelist[test] + pathmatch
print 'old line:', line
line = line.replace(test, repstring)
print 'new line:', line
f.write(line)
Но то, что заканчивается, заключается в том, что я получаю только несколько строк (обновляется правильно, заметьте, но повторяется ранее в файле) исправлено. Я думаю, что это вопрос о проблеме, afaict.
* Также: я хотел бы знать, как только заменить текст на первый экземпляр соответствия, например, я не хочу сопоставлять отображаемый текст, только базовый href.
Ответы
Ответ 1
Сначала вы хотите написать строку, соответствует ли она шаблону или нет. В противном случае вы выписываете только согласованные строки.
Во-вторых, между чтением строк и написанием результатов вам нужно либо обрезать файл (может f.seek(0)
, затем f.truncate()
), либо закрыть оригинал и снова открыть его. Выбрав первое, я бы получил что-то вроде:
fpath = os.path.join(thisdir, filename)
with open(fpath, 'r+') as f:
lines = f.readlines()
f.seek(0)
f.truncate()
for line in lines:
if '<a href="' in line:
for test in filelist:
pathmatch = file_match(line, test)
if pathmatch is not None:
repstring = filelist[test] + pathmatch
line = line.replace(test, repstring)
f.write(line)
Ответ 2
- Откройте файл для чтения и скопируйте все строки в память. Закройте файл.
- Примените свои преобразования к строкам в памяти.
- Откройте файл для записи и записи всех строк текста в памяти.
with open(filename, "r") as f:
lines = (line.rstrip() for line in f)
altered_lines = [some_func(line) if regex.match(line) else line for line in lines]
with open(filename, "w") as f:
f.write('\n'.join(altered_lines) + '\n')
Ответ 3
A (относительно) безопасный способ замены строки в файле.
#!/usr/bin/python
# defensive programming style
# function to replace a line in a file
# and not destroy data in case of error
def replace_line(filepath, oldline, newline ):
"""
replace a line in a temporary file,
then copy it over into the
original file if everything goes well
"""
# quick parameter checks
assert os.exists(filepath) # !
assert ( oldline and str(oldline) ) # is not empty and is a string
assert ( newline and str(newline) )
replaced = False
written = False
try:
with open(filepath, 'r+') as f: # open for read/write -- alias to f
lines = f.readlines() # get all lines in file
if oldline not in lines:
pass # line not found in file, do nothing
else:
tmpfile = NamedTemporaryFile(delete=True) # temp file opened for writing
for line in lines: # process each line
if line == oldline: # find the line we want
tmpfile.write(newline) # replace it
replaced = True
else:
tmpfile.write(oldline) # write old line unchanged
if replaced: # overwrite the original file
f.seek(0) # beginning of file
f.truncate() # empties out original file
for tmplines in tmpfile:
f.write(tmplines) # writes each line to original file
written = True
tmpfile.close() # tmpfile auto deleted
f.close() # we opened it , we close it
except IOError, ioe: # if something bad happened.
printf ("ERROR" , ioe)
f.close()
return False
return replaced and written # replacement happened with no errors = True
(примечание: это заменяет только целые строки и все строки, которые соответствуют в файле)