2

I am trying to add delimiter in a fixed width text file at multiple positions given in a list below. I am using python 3.4.4

file:

a.txt

@4a54667inthenationof pr
@3453343bewithmeincaseof
list=[4,8, 11]

As, there are 1000s of lines in a file so I am trying to achieve this by iterating over a list and adding it in a newline variable but delimiters are not getting added in proper places.

code:

with open('output.txt', 'w') as outfile:
    with open('a.txt', 'r') as infile:
        for line in infile:
            for l in list:
                newline = line[:l] + '|' + line[l:]
                outfile.write(newline)
outfile.close() 

Current output: is generating wrong

output.txt

@4a5|4667inthenationof pr
@4a54667|inthenationof pr
@4a54667int|henationof pr
@345|3343bewithmeincaseof@3453343|bewithmeincaseof@3453343bew|ithmeincaseof

Expected output: delimiters at fixed positions 4, 8 and 11

@4a5|466|7i|nthenationof pr
@345|334|3b|ewithmeincaseof
  • I'm not sure if your final output is what you meant, since if the positions are positions in the original file as it is, then the expected output for the first line for example should be: `@4a5|4667|int|henationof pr`. – kabanus Jul 01 '20 at 05:21
  • You should not use keywords like `list` for variable names. – Glenn Mackintosh Jul 01 '20 at 05:41

4 Answers4

2

I think the output which is 4 in the output file is due to the for loop and in order to get rid of it you should put the outfile.write() in the first for loop. Since you want to the pipe symbol '|' in the 4,8 and 11 position you can just insert it to the list of line and join to write the new output file

lit=[4,8, 11]
with open('output.txt', 'w') as outfile:
    with open('a.txt', 'r') as infile:
        for line in infile:
            line = list(line)
            for i in lit:
                line.insert(i,'|')
            outfile.write("".join(line))
outfile.close() 
DaVinci
  • 868
  • 1
  • 7
  • 25
1

The problem is that you're writing to the output file while you iterate over the items in list. The following code should fix the problem. Also, try avoiding using keywords as variable names, so rename list to something else.

Code

positions = [4, 8, 11]

with open('output.txt', 'w') as outfile:
    with open('a.txt', 'r') as infile:
        for line in infile:
            newline = line
            for l in positions:
                newline = newline[:l] + '|' + newline[l:]
            outfile.write(newline)

Output

@4a5|466|7i|nthenationof pr
@345|334|3b|ewithmeincaseof
zmike
  • 1,090
  • 10
  • 24
1

First, I advise against using builtins as variable names, so I suggest renaming list to something like positions. Next:

for l in positions:
    newline = line[:l] + '|' + line[l:]
    outfile.write(newline)

Try run in your head what you are doing here:

  • For every position in positions
    1. Set newline to the original line with the delimiter at the position.
    2. Write newline to the file as is, with the single delimiter.

So basically for every position you are making copy of the line at that position. Probably, this is closer to what you meant (not using any Python shenanigans):

newline = line
pos_counter = 0
for pos in positions:
    pos += pos_counter
    newline = newline[:pos] + '|' + newline[pos:]
    pos_counter += 1
outfile.write(newline)

Note since newline keeps getting bigger I have to keep increasing pos to take account for that. Also note I am writing when I am done amending the line. To avoid book keeping you can go backward:

for pos in positions[::-1]:
    newline = newline[:pos] + '|' + newline[pos:]

since now the newline gets longer after the current insertion position. Finally with shenanigans:

newline = '|'.join(line[start:stop] for start, stop in zip([0]+positions, positions+[-1]))
kabanus
  • 24,623
  • 6
  • 41
  • 74
  • 1
    `pos += 1` is not necessary. – DYZ Jul 01 '20 at 04:59
  • The OP had accounted for the increasing size of the string resulting from adding the separators with the values in his `list` That is why the second one was 8 instead of 7 and the third was 11 instead of 9. – Glenn Mackintosh Jul 01 '20 at 05:37
1

This is another approach using .insert

Ex:

lst=[4,8, 11]
with open(filename_1) as infile, open(filename_2, 'w') as outfile:
    for line in infile:
        line = list(line)
        for p in lst:
            line.insert(p, "|")       #insert `|` @ given pos
        outfile.write("".join(line))  #join & write

Output:

@4a5|466|7i|nthenationof pr
@345|334|3b|ewithmeincaseof
Rakesh
  • 81,458
  • 17
  • 76
  • 113