Как заменить (обновить) текст в строке строки за строкой

Я пытаюсь заменить текст в текстовом файле, читая каждую строку, тестируя его, а затем записывая, если его нужно обновить. Я НЕ хочу сохранять как новый файл, так как мой 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 

(примечание: это заменяет только целые строки и все строки, которые соответствуют в файле)