0

I have a python function that is supposed to receive:

  • A file path
  • A list of tuples with old value to find and new value to replace it.

The script is supposed to produce the same file modified with the tuple values (old to new). This is what I have tried so far:

def inplace_change(new_filename, old_string_new):
        for old_new in old_string_new:
            with open(new_filename, "rt") as fin:
                with open(new_filename, "wt") as fout:
                    for line in fin:
                        fout.write(line.replace(old_new[0], old_new[1]))

I generally pass them alist of tuples like this:

[('PidFile=/path/xxx.pid',
        'PidFile=/path/xxx.' + container_name + '.pid'),
       ('LogFile=/xx/log/nc_zabbix_agentd.log',
        'LogFile=/xx/log/yyyy.' + container_name + '.log')
    ...]

Then a normal path where the file is.

I manage to replace only a tuple (single old string with new string) very easily, but when I have the list I can not get the logic to get this done. Any ideas?

wti
  • 494
  • 4
  • 19

2 Answers2

2

The culprit:

for old_new in old_string_new:

Should have been:

for old_val, new_val in old_string_new:

Changing this line:

fout.write(line.replace(old_new[0], old_new[1]))

to this:

fout.write(line.replace(old_val, new_val))

I have minimized your problem, the following should be very easy to understand:

old_string_new  = [ ('old1', 'new1'), ('old2', 'new2'), ('old3', 'new3')]

for old_val, new_val in old_string_new: 
    print(old_val, new_val)

OUTPUT:

old1 new1
old2 new2
old3 new3

EDIT:

A detailed answer with tested code, Suppose we have a file as follow:

list.txt:

old1 hello there
okay old2 you will be replaced
haha bye bye old3

With the Code:

import fileinput as fp

def inplace_change(filename, old_string_new):
    for old_val, new_val in old_string_new:
        with fp.FileInput(filename, inplace=True, backup='.bak') as file:
            for line in file:
                print(line.replace(old_val, new_val), end='')


old_string_new  = [('old1', 'new1'), ('old2', 'new2'), ('old3', 'new3')]
inplace_change('list.txt', old_string_new)

OUTPUT (list.txt):

new1 hello there
okay new2 you will be replaced
haha bye bye new3
DirtyBit
  • 16,613
  • 4
  • 34
  • 55
  • It does not change the final output. it still does not work. same result; a blank file. – wti Mar 26 '19 at 09:58
  • I highly doubt, post the code that is using this approach in your question. – DirtyBit Mar 26 '19 at 09:59
  • @wti I am adding a detailed answer while I do so, know that you need `a+` not `wt` – DirtyBit Mar 26 '19 at 10:04
  • 1
    @wti Kindly check the edited version of the answer. – DirtyBit Mar 26 '19 at 10:08
  • hi @DirtyBit, thanks for your answer, it seems with a bit of work could be the right answer, but the answer from geckos, works out of the box and came first. I get this error with your anser: `print(line.replace(old_val, new_val), end='') SyntaxError: invalid syntax` seems it could be solved easily in any case, but I already have a working answer. – wti Mar 27 '19 at 01:08
  • @wti Ah, that is because youre using Python 2.x. No worries, glad it helped! :) – DirtyBit Mar 27 '19 at 05:25
1

Try something like this

import os

def replace_in_file(fn, replaces):
    with open(fn, 'r') as f1, open(fn+'.new', 'w') as f2:
        for line in f1.readlines():
            for a, b in replaces:
                line = line.replace(a, b)
            f2.write(line)
    os.rename(fn+'.new', fn)

replace_in_file('foo.txt', (('foo', 'bar'), ('hey', 'ho')))
geckos
  • 5,687
  • 1
  • 41
  • 53