Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inserting Line at Specified Position of a Text File

I have a text file which looks like this:

blah blah
foo1 bar1
foo1 bar2
foo1 bar3
foo2 bar4
foo2 bar5
blah blah

Now I want to insert 'foo bar' between 'foo1 bar3' and 'foo2 bar4'.

This is how I did it:

import shutil

txt = '1.txt'
tmptxt = '1.txt.tmp'

with open(tmptxt, 'w') as outfile:
    with open(txt, 'r') as infile:
        flag = 0
        for line in infile:
            if not line.startswith('foo1') and flag == 0:
                outfile.write(line)
                continue
            if line.startswith('foo1') and flag == 0:
                flag = 1
                outfile.write(line)
                continue
            if line.startswith('foo1') and flag == 1:
                outfile.write(line)
                continue
            if not line.startswith('foo1') and flag == 1:
                outfile.write('foo bar\n')
                outfile.write(line)
                flag = 2
                continue
            if not line.startswith('foo1') and flag == 2:
                outfile.write(line)
                continue

shutil.move(tmptxt, txt)

This works for me, but looks rather ugly.

like image 255
Wang Dingwei Avatar asked Aug 25 '09 03:08

Wang Dingwei


People also ask

How do I put text in a specific position of a file in Python?

seek() method In Python, seek() function is used to change the position of the File Handle to a given specific position. File handle is like a cursor, which defines from where the data has to be read or written in the file.

How do you add a line to a file in Linux?

You need to use the >> to append text to end of file. It is also useful to redirect and append/add line to end of file on Linux or Unix-like system.

How do you write to a specific line in Python?

We will first open the file in read-only mode and read all the lines using readlines(), creating a list of lines storing it in a variable. We will make the necessary changes to a specific line and after that, we open the file in write-only mode and write the modified data using writelines().


3 Answers

The best way to make "pseudo-inplace" changes to a file in Python is with the fileinput module from the standard library:

import fileinput

processing_foo1s = False

for line in fileinput.input('1.txt', inplace=1):
  if line.startswith('foo1'):
    processing_foo1s = True
  else:
    if processing_foo1s:
      print 'foo bar'
    processing_foo1s = False
  print line,

You can also specify a backup extension if you want to keep the old version around, but this works in the same vein as your code -- uses .bak as the backup extension but also removes it once the change has successfully completed.

Besides using the right standard library module, this code uses simpler logic: to insert a "foo bar" line after every run of lines starting with foo1, a boolean is all you need (am I inside such a run or not?) and the bool in question can be set unconditionally just based on whether the current line starts that way or not. If the precise logic you desire is slightly different from this one (which is what I deduced from your code), it shouldn't be hard to tweak this code accordingly.

like image 145
Alex Martelli Avatar answered Oct 11 '22 06:10

Alex Martelli


Adapting Alex Martelli's example:

import fileinput
for line in fileinput.input('1.txt', inplace=1):
 print line,
 if line.startswith('foo1 bar3'):
     print 'foo bar'
like image 23
Eric Lee Avatar answered Oct 11 '22 08:10

Eric Lee


Recall that an iterator is a first-class object. It can be used in multiple for statements.

Here's a way to handle this without a lot of complex-looking if-statements and flags.

with open(tmptxt, 'w') as outfile:
    with open(txt, 'r') as infile:
        rowIter= iter(infile)
        for row in rowIter:
            if row.startswith('foo2'): # Start of next section
                 break
            print row.rstrip(), repr(row)
        print "foo bar"
        print row
        for row in rowIter:
            print row.rstrip()
like image 9
S.Lott Avatar answered Oct 11 '22 06:10

S.Lott