我想循环一个文本文件的内容,并在一些行上进行搜索和替换,并将结果写回文件。我可以先把整个文件加载到内存中,然后再把它写回来,但这可能不是最好的方法。

在下面的代码中,做到这一点的最佳方法是什么?

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

当前回答

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

其他回答

扩展@Kiran的回答,我认为它更简洁和python化,这增加了编解码器来支持UTF-8的读写:

import codecs 

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


def replace(source_file_path, pattern, substring):
    fh, target_file_path = mkstemp()

    with codecs.open(target_file_path, 'w', 'utf-8') as target_file:
        with codecs.open(source_file_path, 'r', 'utf-8') as source_file:
            for line in source_file:
                target_file.write(line.replace(pattern, substring))
    remove(source_file_path)
    move(target_file_path, source_file_path)

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

import fileinput

for line in fileinput.input("test.txt", inplace=True):
    print('{} {}'.format(fileinput.filelineno(), line), end='') # for Python 3
    # print "%d: %s" % (fileinput.filelineno(), line), # for Python 2

这里的情况是:

原始文件被移动到备份文件中 标准输出被重定向到循环中的原始文件 因此,任何打印语句都写回原始文件

Fileinput有更多附加功能。例如,它可以用来自动操作sys. exe中的所有文件。Args[1:],而不需要显式地迭代它们。从Python 3.2开始,它还为在with语句中使用提供了方便的上下文管理器。


虽然fileinput对于一次性脚本非常有用,但我在实际代码中使用它时会很谨慎,因为必须承认它不是很可读或熟悉。在实际的(生产)代码中,多写几行代码来明确过程,从而使代码可读是值得的。

有两种选择:

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

这应该工作:(就地编辑)

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"),

使用hamishmcn的答案作为模板,我能够在文件中搜索与我的正则表达式匹配的一行,并将其替换为空字符串。

import re 

fin = open("in.txt", 'r') # in file
fout = open("out.txt", 'w') # out file
for line in fin:
    p = re.compile('[-][0-9]*[.][0-9]*[,]|[-][0-9]*[,]') # pattern
    newline = p.sub('',line) # replace matching strings with empty string
    print newline
    fout.write(newline)
fin.close()
fout.close()

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

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.")