如何逐行替换(更新)文件中的文本

时间:2011-01-24 04:39:06

标签: python

我试图通过读取每一行,测试它,然后在需要更新时写入来替换文本文件中的文本。我不想保存为新文件,因为我的脚本已经先备份文件并对备份进行操作。

这是我到目前为止的...我从os.walk()得到fpath,我保证pathmatch var正确返回:

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)

但最终发生的事情是,我只得到了几行(正确更新,请注意,但在文件的前面重复)已更正。我认为这是一个范围界定的问题。

*另外:我想知道如何仅在匹配的第一个实例上替换文本,例如,我不想匹配显示文本,只有底层的href。

3 个答案:

答案 0 :(得分:10)

  1. 打开文件进行读取,并将所有行复制到内存中。关闭文件。
  2. 将转换应用于内存中的行。
  3. 打开文件进行写入,并写出内存中的所有文本行。

  4. 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')
    

答案 1 :(得分:9)

首先,您想要写一行是否与模式匹配。否则,你只会写出匹配的行。

其次,在读取行和写入结果之间,您需要截断文件(可以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 :(得分:1)

替换文件中一行的(相对)安全方法。

#!/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 

(注意:这只替换了整行,以及文件中匹配的所有行)