简体   繁体   中英

Replacing characters in a string loop

I have a template txt file. This txt file is to be written as 10 new files but each with some characters changed according to a list of arbitrary values:

with open('template.txt') as template_file:
     template = template_file.readlines()
     for i in range(10):
          with open('output_%s.txt' % i, 'w') as new_file:
               new_file.writelines(template_file)

The length of the list is the same as the number of new files (10).

I am trying to replace part of the 2nd line of each new file with the value in my list.

So for example, I want line 2, positions [5:16] in each new file replaced with the respective value in the list..

File 0 will have element 0 of the list File 1 will have element 1 of the list etc..

I tried using the replace() method:

list = [element0, element1, etc...element9]

for i in template_file:
    i.replace(template_file[2][5:16], list_element)

But it will only replace all the files with the first list element... It wont loop over.

Any help appreciated

There are a couple of problems I can find which prevent your code from working:

  • You should write template out, which is a list of lines, not template_file , which is a file object
  • In Python, strings are immutable, meaning they cannot be changed. The replace function does not change the string, it returns a new copy of the string. Furthermore, replace will replace a substring with a new text, regardless of where that substring is. If you want to replace at a specific index, I suggest to slice the string yourself. For example:

     line2 = '0123456789ABCDEFG' element = '-ho-ho-ho-' line2 = line2[:5] + element + line2[16:] # line2 now is '01234-ho-ho-ho-G' 
  • Please do not use list as a variable name. It is a type, which can be used to construct a new list as such:

     empty = list() # ==> [] letters = list('abc') # ==> ['a', 'b', 'c'] 
  • The expression template_file[2][5:16] is incorrect: First, it should be template , not template_file . Second, the second line should be template[1] , not template[2] since Python list are zero based

  • The list_element variable is not declared in your code

Solution 1

That being said, I find that it is easier to structure your template file as a real template with placeholders. I'll talk about that later. If you still insist to replace index 5-16 of line 2 with something, here is a solution I tested and it works:

with open('template.txt') as template_file:
    template = template_file.readlines()
    elements = ['ABC', 'DEF', 'GHI', 'JKL']
    for i, element in enumerate(elements):
        with open('output_%02d.txt' % i, 'w') as out_file:
            line2 = template[1]
            line2 = line2[:5] + element + line2[16:]
            for line_number, line in enumerate(template, 1):
                if line_number == 2:
                    line = line2
                out_file.write(line)

Notes

  • The code writes out all lines, but with special replacement applies to line 2
  • The code is clunky, nested deeply
  • I don't like having to hard code the index numbers (5, 16) because if the template changes, I have to change the code as well

Solution 2

If you have control of the template file, I suggest to use the string.Template class to make search and replace easier. Since I don't know what your template file looks like, I am going to make up my own template file:

line #1
This is my ${token} to be replaced
line #3
line #4

Note that I intent to replace ${token} with one of the elements in the code. Now on to the code:

import string

with open('template.txt') as template_file:
    template = string.Template(template_file.read())
    elements = ['ABC', 'DEF', 'GHI', 'JKL']
    for i, element in enumerate(elements):
        with open('output_%02d.txt' % i, 'w') as out_file:
            out_file.write(template.substitute(token=element))

Notes

  • I read the whole file in at once with template_file.read() . This could be a problem if the template file is large, but previous solution als ran into the same performance issue as this one
  • I use the string.Template class to make search/replace easier
  • Search and replace is done by substitute(token=element) which said: replace all the $token or ${token} instances in the template with element .
  • The code is much cleaner and dare I say, easier to read.

Solution 3

If the template file is too large to fit in memory at once, you can modify the first solution to read it line-by-line instead of reading all lines in at once. I am not going to present that solution here, just a asuggestion.

Looks like you need

list = [element0, element1, etc...element9]
for i in list:
    template_file = template_file.replace(template_file[2][5:16], i)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM