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

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

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

当前回答

正如lassevk所建议的,在运行时写出新文件,下面是一些示例代码:

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

其他回答

根据托马斯·沃特内达尔的回答。 然而,这并没有准确地回答原始问题的行对行部分。函数仍然可以在行对行的基础上进行替换

此实现替换文件内容而不使用临时文件,因此文件权限保持不变。

此外,re.sub代替replace,允许正则表达式替换而不是纯文本替换。

将文件读取为单个字符串而不是逐行读取允许多行匹配和替换。

import re

def replace(file, pattern, subst):
    # Read contents from file as a single string
    file_handle = open(file, 'r')
    file_string = file_handle.read()
    file_handle.close()

    # Use RE package to allow for replacement (also allowing for (multiline) REGEX)
    file_string = (re.sub(pattern, subst, file_string))

    # Write contents to file.
    # Using mode 'w' truncates the file.
    file_handle = open(file, 'w')
    file_handle.write(file_string)
    file_handle.close()

使用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()

如果您删除缩进如下所示,它将在多行中搜索和替换。 请看下面的例子。

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

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

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

如果你想要一个通用函数,用其他文本替换任何文本,这可能是最好的方法,特别是如果你是regex的粉丝:

import re
def replace( filePath, text, subs, flags=0 ):
    with open( filePath, "r+" ) as file:
        fileContents = file.read()
        textPattern = re.compile( re.escape( text ), flags )
        fileContents = textPattern.sub( subs, fileContents )
        file.seek( 0 )
        file.truncate()
        file.write( fileContents )