-3

There's this line in 'file.txt' that says:

memcpy(buffer, "", 64)

I want to write a Python script that reads this file.txt and locates this line in it. Then, it proceeds to insert a specific string (stored in a variable 'data') between the two quotes ("") in that line.

For example, if the variable data contains the value 'foo bar', then the line would be modified by the Python script to:

memcpy(buffer, "foo bar", 64)

Here's what I have tried:

data = "foo bar"

with open('file.txt') as in_file:
    in_buffer = in_file.readlines()

with open('new.txt', "w") as out_file:
    for line in in_buffer:
        if line == 'memcpy(buffer, "", 64)':
            out_file.write("memcpy(buffer, \"data\", 64)")
        else:
            out_file.write(line)

It didn't work because it created the exact same replica of the file in new.txt without making any modifications.

learnerX
  • 1,022
  • 1
  • 18
  • 44
  • possible duplicate of [Is it possible to modify lines in a file in-place?](http://stackoverflow.com/questions/5453267/is-it-possible-to-modify-lines-in-a-file-in-place) – Peter Wood Mar 02 '15 at 20:20
  • @PeterWood I did take a look at those questions. I did write the code after referring to these answers. However, I couldn't make it work. – learnerX Mar 02 '15 at 20:25
  • The line will have a newline at the end. `line == 'memcpy(buffer, "", 64)\n'` – Peter Wood Mar 02 '15 at 20:46
  • `$ sed 's/^wrong line$/wrong corrected line/' < file.txt > file.new` – gboffi Mar 03 '15 at 07:34

4 Answers4

2

Please use

if line == 'memcpy(buffer, "", 64)\n':
     out_file.write('memcpy(buffer, "'+data+'", 64)\n')

instead of yours

if line == 'memcpy(buffer, "", 64)':
        out_file.write("memcpy(buffer, \"data\", 64)")

because the readlines() method DOESN'T strip newlines.

Post Scriptum Please note that not only the condition has to be rewritten, but also your if body needs a bit of reengineering, your version would write

memcpy(buffer, "data", 64)

to the output file.

gboffi
  • 22,939
  • 8
  • 54
  • 85
2

Another answer to your question, using the suggestion in the above comment by Peter Wood

Using the code shown below

$ cat mod_memcpy.py
from fileinput import input
data = "Papa Smurf"
for line in input(inline=1, backup=".bak"):
    if line != 'memcpy(buffer, "", 64)\n':
        print line, # << note the comma
    else:
       print 'memcpy(buffer, "'+data+'", 64)'

in the following way

$ python2 mod_memcpy.py file.txt

you'll get a backup file, file.bak file.txt.bak and a modified file.txt with the lines

memcpy(buffer, "", 64)

replaced by

memcpy(buffer, "Papa Smurf", 64)

The reference documentation for fileinput is here (Python 2) or here (Python3).

I'd like to add that the fileinput module is the answer to this kind of problems, i.e., modifying a file or a sequence of files.


Addendum the following is copied and pasted (with a slight editing to shorten the files...) from the shell

$ cat c.py
from __future__ import print_function
from fileinput import input
for line in input(inplace=True, backup='.bak'):
    print("00", line, end="")
$ cat dele.txt # the real file is a bit longer, hence the ellipsis
Company ABC-GH Date:31.12.2012
financial statement:4
...
$ python2 c.py dele.txt
$ cat dele.txt
00 Company ABC-GH Date:31.12.2012
00 financial statement:4
...
$ mv dele.txt.bak dele.txt
$ python3 c.py dele.txt
$ cat dele.txt
00 Company ABC-GH Date:31.12.2012
00 financial statement:4
...
$ mv dele.txt.bak dele.txt

It seems that the relevant part of the code, i.e.,

for line in input(inline=1, backup=".bak"):

works with Python 2.7 and Python 3.4 all the same and I have to confess that I do not understand which is the reason of the problem that the OP has experienced with my code.

Community
  • 1
  • 1
gboffi
  • 22,939
  • 8
  • 54
  • 85
  • Tried executing it; got this: "Traceback (most recent call last): File "replace.py", line 4, in for line in input(inline=1, backup=".bak"): TypeError: input() takes no keyword arguments" – learnerX Mar 02 '15 at 23:26
1

This code add the condition part to the horns code. Use re modules sub function to replace the matching string.

import re

filename = "file.txt"
regex = re.compile(r'(memcpy\s*\(\s*buffer\s*,\s*")\s*("\s*,\s*64\s*)')
with open(filename) as in_file:
    in_buffer = in_file.readlines()

data = "foo bar"
with open(filename, "w") as out_file:
    for line in in_buffer:
        out_file.write(regex.sub(r'\g<1>'+data+'\g<2>', line))
learnerX
  • 1,022
  • 1
  • 18
  • 44
Vinod Sharma
  • 883
  • 6
  • 13
  • Your code works! However, you have hard-coded the value "foo bar" in the last line. I want to be able to insert any value stored in 'data' variable. How would I do that? – learnerX Mar 02 '15 at 21:01
  • @intellikid You need to go and try it, then ask another question if you're still stuck after searching. – Peter Wood Mar 02 '15 at 21:20
  • Yep it was hardcoded. Now fixed to a variable value. it's a simple fix: just create a replace pattern by joining two strings. – Vinod Sharma Mar 02 '15 at 22:25
0
with open(filename) as in_file:
    in_buffer = in_file.readlines()

with open(filename, "w") as out_file:
    for line in in_buffer:
        if condition:
            out_file.write("something else")
        else:
            out_file.write(line)
horns
  • 1,843
  • 1
  • 19
  • 26
  • Thank you. I just tried your code (please see edit made to the question above). This time it created the exact replica of the file and did not make the modification. I'm guessing there's something wrong with the condition I specified. Could you please suggest how to specify the condition? – learnerX Mar 02 '15 at 20:41
  • Just replace `condition` with `line == 'memcpy(buffer, "", 64)'` or whatever else you want. – horns Mar 02 '15 at 23:04