change a string in text file then write it

Alex Martelli aleaxit at yahoo.com
Mon Nov 6 03:17:19 EST 2000


"Jose" <spamzostar at bitstream.net> wrote in message
news:3A0660E4.2975 at bitstream.net...
> Hey all,
> I am reading in a simple text file with readlines(foo)
> I go into a loop to simple search a regexp, I can find
> this regexp ok.  I change a part of the string using
> string.replace(...) and it actually does change it ok,

Not really.  Strings are immutable.  The replace method
does not change the string it's applied to (NOTHING can
change a string!), it produces a NEW string which is "like
the old one" but "with the requested change".

You have to use *assignment* to bind the new string
to wherever you desire (presumably, in this case, to
the same item in the "lines" list which was bound to
the "old string").  Are you doing so...?


> BUT when I now want to write this change to a file
> using simple output.writelines(lines) It does not know
> that I have changed a piece of a string on a line.

If you have not explicitly changed the "lines" list,
by assigning to its items, there will indeed be no
'knowledge' left in it of what operations you've done.

> There obviously is a way to change a small piece of
> a string on a line and then write it back out to a
> file but I am having difficulty, new to python.


It seems to me that what you're trying to do is
something like:

lines = open("somefile.txt").readlines()
for i in range(len(lines)):
    if re.search(myre, lines[i]):
        lines[i] = lines[i].replace('foo','bar')
open("otherfile.txt","w").writelines(lines)

or, in old Python 1.5.2 or earlier, basically the
same thing but with the 4th line changed to
        lines[i] = string.replace(lines[i],'foo','bar')

(this also works in Python 2.0, for compatibility).


I suspect that the loop you're using instead is more
like the following:

for line in lines:
    if re.search(myre, line):
        line = string.replace(line,'foo','bar')

i.e., you're assigning the result of the replacement
to the loop-variable, leaving the lines list intact
and unchanged.  This seems the likeliest explanation.


Note that, if you want to do the replacement "in place"
(write out to the same file you've read), the fileinput
module is very handy for that purpose:

for line in fileinput.input("thefile.txt", inplace=1):
    if re.search(myre, line):
        line = string.replace(line,'foo','bar')
    print line

the 'print line' is redirected by fileinput to the
filename being read (the original file having been
temporarily 'shunted aside' under a fake name -- it
will be removed at the end of the loop, unless the
further argument backup='.bak' [or whatever] is also
passed to the .input function).  This saves having to
keep the whole file in memory at once, which is handy
for huge files, but is no help if you want to write
the results to a *different* file (in that case, your
approach based on readlines/modify the list/writelines
is just fine for most files -- for truly huge files,
you'll no doubt want to operate line by line rather
than all-at-once, though -- but, you do have to make
your modifications to *the list*, with some statement
such as 'lines[i] = ...whatever...").


Alex






More information about the Python-list mailing list