6

How can I replace a string with another string, within a given text file. Do I just loop through readline() and run the replacement while saving out to a new file? Or is there a better way?

I'm thinking that I could read the whole thing into memory, but I'm looking for a more elegant solution...

Thanks in advance

John B
  • 20,062
  • 35
  • 120
  • 170
  • Is there a particular reason you don't want to loop through lines? It's probably the best solution. – cobbal Jun 02 '10 at 20:57
  • I don't know... I was just wondering if there was a better way I guess. Rather than creating a new file and removing the old one. – John B Jun 02 '10 at 21:00
  • by creating the new file you remove the need to have the whole file in memory... and if you are doing a re.sub you should make sure you use re.compile first (and then use the returned instance's sub method) – Terence Honles Jun 02 '10 at 21:17

2 Answers2

12

fileinput is the module from the Python standard library that supports "what looks like in-place updating of text files" as well as various other related tasks.

for line in fileinput.input(['thefile.txt'], inplace=True):
    print(line.replace('old stuff', 'shiny new stuff'), end='')

This code is all you need for the specific task you mentioned -- it deals with all of the issues (writing to a different file, removing the old one when done and replacing it with the new one). You can also add a further parameter such as backup='.bk' to automatically preserve the old file as (in this case) thefile.txt.bk, as well as process multiple files, take the filenames to process from the commandline, etc, etc -- do read the docs, they're quite good (and so is the module I'm suggesting!-).

Arnaud P
  • 12,022
  • 7
  • 56
  • 67
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 2
    Avoid using "print" and use "sys.stdout.write" instead if you don't wan't "print" to add blank line and CTRL-M after every line – Badisi Sep 13 '13 at 18:36
  • 1
    @Badisi You can accomplish that by setting `print`'s parameter `end`, which by default is set to `\n`, to an empty string. I.e: `print(line, end='')`. See https://docs.python.org/3.3/library/functions.html#print – Daniel Jonsson Dec 30 '14 at 11:10
4

If the file can be read into memory at once, I'd say that

old = myfile.read()
new = old.replace("find this", "replace by this")
output.write(new)

is at least as readable as

for line in myfile:
   output.write(line.replace("find this", "replace by this"))

and it might be a little faster, but in the end it probably doesn't really matter.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561