tags:

views:

9123

answers:

6

I want to loop over the contents of a text file and do a search and replace on some lines and write the result back to the file. I could first load the whole file in memory and then write it back, but that probably is not the best way to do it.

What is the best way to do this, within the following code?

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
A: 

Create a new file, copy lines from the old to the new, and do the replacing before you write the lines to the new file.

Lasse V. Karlsen
+6  A: 

I guess something like this should do it. It basically writes the content to a new file and replaces the old file with the new file:

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

def replace(file, pattern, subst):
    #Create temp file
    fh, abs_path = mkstemp()
    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)
Thomas Watnedal
+1  A: 

As lassevk suggests, write out the new file as you go, here is some example code:

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

Use the fileinput module. For example, the following adds line numbers to a file, in-place:

import fileinput

for line in fileinput.input("test.txt", inplace=1):
    print "%d: %s" % (fileinput.filelineno(), line),
Eli Bendersky
I know this only has two lines in it, however I don't think the code is very expressive in itself. Because if you think for a sec, if you didn't know the function, there are very few clues in what is going on. Printing the line number and the line is not the same as writing it ... if you get my gist...
chutsu
+6  A: 

Heres another example. Tested, and will match search & replace patterns

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)

Example use:

replaceAll("/fooBar.txt","Hello\sWorld!$","Goodbye\sWorld.")
Jason
+2  A: 

This should work: (inplace editiing)

import fileinput

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