在Python中搜索并替换文件中的一行

时间:2020-03-05 18:46:19  来源:igfitidea点击:

我想遍历文本文件的内容,进行搜索并替换某些行,然后将结果写回到文件中。我可以先将整个文件加载到内存中,然后再写回,但这可能不是最好的方法。

在以下代码中,执行此操作的最佳方法是什么?

f = open(file)
for line in f:
    if line.contains('foo'):
        newline = line.replace('foo', 'bar')
        # how to write this newline back to the file

解决方案

回答

创建一个新文件,将行从旧复制到新,并在将行写入新文件之前进行替换。

回答

我想应该做些类似的事情。它基本上将内容写入新文件,并用新文件替换旧文件:

from tempfile import mkstemp
from shutil import move
from os import fdopen, remove

def replace(file_path, pattern, subst):
    #Create temp file
    fh, abs_path = mkstemp()
    with fdopen(fh,'w') as new_file:
        with open(file_path) as old_file:
            for line in old_file:
                new_file.write(line.replace(pattern, subst))
    #Remove original file
    remove(file_path)
    #Move new file
    move(abs_path, file_path)

回答

就像lassevk建议的那样,随时随地写出新文件,这是一些示例代码:

fin = open("a.txt")
fout = open("b.txt", "wt")
for line in fin:
    fout.write( line.replace('foo', 'bar') )
fin.close()
fout.close()

回答

最短的方法可能是使用fileinput模块。例如,以下代码将行号就地添加到文件中:

import fileinput

for line in fileinput.input("test.txt", inplace=True):
    print "%d: %s" % (fileinput.filelineno(), line),

这里发生的是:

  • 原始文件已移至备份文件
  • 标准输出在循环内重定向到原始文件
  • 因此,任何print语句都会写回到原始文件中

fileinput具有更多的优点。例如,它可用于自动处理sys.args [1:]中的所有文件,而无需显式遍历它们。从Python 3.2开始,它还提供了一个方便的上下文管理器,可在with语句中使用。

尽管fileinput非常适合一次性脚本,但我会警惕在实际代码中使用它,因为诚然,它不太可读或者不熟悉。在实际(生产)代码中,值得花几行代码来使过程明确,从而使代码可读。

有两种选择:

  • 该文件不是太大,我们可以将其全部读取到内存中。然后关闭文件,以写入模式将其重新打开,然后将修改后的内容写回。
  • 该文件太大,无法存储在内存中。我们可以将其移到一个临时文件中并打开它,逐行读取它,然后写回到原始文件中。请注意,这需要两倍的存储空间。

回答

这是另一个经过测试的示例,它将匹配搜索和替换模式:

import fileinput
import sys

def replaceAll(file,searchExp,replaceExp):
    for line in fileinput.input(file, inplace=1):
        if searchExp in line:
            line = line.replace(searchExp,replaceExp)
        sys.stdout.write(line)

使用示例:

replaceAll("/fooBar.txt","Hello\sWorld!$","Goodbye\sWorld.")

回答

这应该起作用:(就地编辑)

import fileinput

# Does a list of files, and
# redirects STDOUT to the file in question
for line in fileinput.input(files, inplace = 1): 
      print line.replace("foo", "bar"),