【问题标题】:how to replace (update) text in a file line by line如何逐行替换(更新)文件中的文本
【发布时间】:2011-01-24 04:39:06
【问题描述】:

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

这是我目前所拥有的......我从 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)

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

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

【问题讨论】:

  • 您是否考虑过简单地使用sed 来代替?
  • @Amber:在方式上。我真的很想完成这个,以后再学习 sed。我几乎完成了这个...... :)
  • @Ignacio:这根本没有帮助(是的,我已经读过了)。我不是在构建一个包罗万象的解析器,所以它真的不适用。
  • 为什么不从备份文件中读取并写入原始文件?

标签: python


【解决方案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)

【讨论】:

  • 非常有帮助...谢谢。一件奇怪的事情是它似乎第一次“几乎”工作,然后我再次运行它,它没有做任何替换......有什么想法吗?我可以尝试追踪它...
  • 您好,raph:我已经稍微修改了我的问题-您能向我解释如何更新代码以允许这种类型的单匹配替换吗?谢谢...
  • 您可以在正则表达式对象上使用 .sub() 方法,计数为 1。另一种可能性是细化您的正则表达式以匹配 a href,而不仅仅是路径。
  • K;如有必要,我会尝试并开始一个新的 q。非常感谢。
  • 嘿,Raph,我在这里发布了一个新 q:stackoverflow.com/questions/4788532/…
【解决方案2】:
  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')

【讨论】:

  • 感谢休的替代建议,但我认为我更喜欢第一个解决方案,因为它与我的尝试相匹配。
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 2017-07-23
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 2018-11-24
    • 2015-11-23
    • 2016-08-08
    • 1970-01-01
    相关资源
    最近更新 更多