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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4778697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 17:28:57  来源:igfitidea点击:

how to replace (update) text in a file line by line

python

提问by jml

I am trying to replace text in a text file by reading each line, testing it, then writing if it needs to be updated. I DO NOT want to save as a new file, as my script already backs up the files first and operates on the backups.

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

Here is what I have so far... I get fpath from os.walk() and I guarantee that the pathmatch var returns correctly:

这是我到目前为止所拥有的......我从 os.walk() 得到 fpath 并且我保证路径匹配 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)

But what ends up happening is that I only get a few lines (updated correctly, mind you, but repeated from earlier in the file) corrected. I think this is a scoping issue, afaict.

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

*Also: I would like to know how to only replace the text upon the first instance of the match, for ex., I don't want to match the display text, only the underlying href.

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

采纳答案by Raph Levien

First, you want to write the line whether it matches the pattern or not. Otherwise, you're writing out only the matched lines.

首先,无论是否与模式匹配,您都想编写该行。否则,您只会写出匹配的行。

Second, between reading the lines and writing the results, you'll need to either truncate the file (can f.seek(0)then f.truncate()), or close the original and reopen. Picking the former, I'd end up with something like:

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

回答by hughdbrown

  1. Open the file for read and copy all of the lines into memory. Close the file.
  2. Apply your transformations on the lines in memory.
  3. Open the file for write and write out all the lines of text in memory.
  1. 打开文件进行读取并将所有行复制到内存中。关闭文件。
  2. 在内存中的行上应用您的转换。
  3. 打开文件并写出内存中的所有文本行。


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

回答by Chris Reid

A (relatively) safe way to replace a line in a file.

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

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

(note: this replaces entire lines only , and all of the lines that match in the file)

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