[Tutor] Find multiple lines in a file

Bill Burns billburns at pennswoods.net
Wed Nov 9 13:44:23 CET 2005


>> I have a PostScript file which contains the following lines (the numbers
>> are for reference only and are *not* in the file):
>>
>> 1 <<
>> 2   /Policies <<
>> 3     /PageSize 3
>> 4   >>
>> 5 >> setpagedevice
>>  
>> I want to open the the file and read it, find these five lines and then
>> replace the lines with something different.
>>
>> Here's some code I'm using to replace just a *single* line in the
>> PostScript file (Note - I'm changing the BoundingBox which is in the
>> same file, but is *not* one of the five lines above).
>>
>> <code>
>> import fileinput
>>
>> class ChangeBBox:
>>      pass
>>
>>      def getBBox(self, filename):
>>              f = open(filename, "rb")
>>              buffer = 1000
>>              tmp = f.readlines(buffer)
>>              f.close()
>>              for line in tmp:
>>                  if line.startswith('%%BoundingBox:'):
>>                      return line.strip()
>>
>>      def modifyBBox(self, filename):
>>          old = self.getBBox(filename)
>>          new = '%%BoundingBox: 0 0 1296 1728'
>>          for line in fileinput.input(filename, inplace=1):
>>              print line.replace(old, new),
>> </code>
> 
> 
> A few comments on the above..
> - You don't need to put these functions in a class, the class isn't 
> adding any value. (OK, it puts the two functions in a single namespace 
> but a module would be more appropriate for that.)
> - The 'pass' statement is not needed.

Yeah, I have the above code in its own module. I've been trying to
'clean-up' my main module (which has way too much 'stuff' going on in
it) and put logical parts & pieces together in separate modules.

Not sure how that pass statement got in there.. must have been from
testing at some point, oops :-)

> - You are adding blank lines to the file - the lines returned by 
> fileinput.input() contain newlines, and print adds another. Avoid this 
> using sys.stdout.write() instead of print.

Much nicer than print! I'll change it.

> - A simpler way to iterate the lines in a file is
>  for line in f:
> 
> In fact the whole pre-search is really not needed, you could write this 
> as (untested!):
> import fileinput, sys
> def modifyBBox(filename):
>  for line in fileinput.input(filename, inplace=1):
>    if line.startswith('%%BoundingBox:'):
>      line = '%%BoundingBox: 0 0 1296 1728\n'
>    sys.stdout.write(line)

Much simpler, will take a look at this.

> 
>> Can anyone offer suggestions on how to find all five lines? I don't
>> think I'll have a problem replacing the lines, it's just getting them
>> all into one variable that stumping me :-)
> 
> 
> OK, none of my suggestions gets you closer to this...the simplest way is 
> if you can read the whole file into memory. Then you can just replace 
> the strings in place and write it out again. For example:
> 
> oldPolicies = '''<<
>  /Policies <<
>    /PageSize 3
>  >>
> 
>>> setpagedevice'''
> 
> 
> newPolicies = 'something completely different'
> 
> f = open(filename)
> data = f.read()
> f.close()
> data.replace(oldPolicies, newPolicies)
> f = open(filename, 'w')
> f.write(data)
> f.close()
> 
> Replacing the bounding box is a little trickier because you have to 
> search for the end of line. You can do this with a regular expression or 
> a couple of find() calls on the string. I'm out of time now so maybe 
> someone else will fill that in.

I'll test out this suggestion later, unfortunately, I've gotta get to
work :-(

Thanks for the reply, Kent!! I really appreciate it!

Bill


More information about the Tutor mailing list