7

I have the following code, which modifies each line of the file test.tex by making a regular expression substitution.

import re
import fileinput

regex=re.compile(r'^([^&]*)(&)([^&]*)(&)([^&]*)')

for line in fileinput.input('test.tex',inplace=1):
    print regex.sub(r'\3\2\1\4\5',line),

The only problem is that I only want the substitution to apply to certain lines in the file, and there's no way to define a pattern to select the correct lines. So, I want to display each line and prompt the user at the command line, asking whether to make the substitution at the current line. If the user enters "y", the substitution is made. If the user simply enters nothing, the substitution is not made.

The problem, of course, is that by using the code inplace=1 I've effectively redirected stdout to the opened file. So there's no way to show output (e.g. asking whether to make the substitution) to the command line that doesn't get sent to the file.

Any ideas?

3
  • fileinput is not the right tool for this job. Just use a standard read-modify-write pattern Commented May 30, 2012 at 15:04
  • @EliBendersky can you point me to an example of doing what the mention? Sorry, I'm very new at Python. Commented May 30, 2012 at 15:06
  • Ideas? Yeah. Don't use fileinput inplace. Do a regular open() on the file, get user input, write to a temp file, when you're done move the temp file to replace the original file. Commented May 30, 2012 at 15:19

2 Answers 2

5

The file input module is really for dealing with more than one input file. You can use the regular open() function instead.

Something like this should work.

By reading the file then resetting the pointer with seek(), we can override the file instead of appending to the end, and so edit the file in-place

import re

regex = re.compile(r'^([^&]*)(&)([^&]*)(&)([^&]*)')

with open('test.tex', 'r+') as f:
    old = f.readlines() # Pull the file contents to a list
    f.seek(0) # Jump to start, so we overwrite instead of appending
    for line in old:
        s = raw_input(line)
        if s == 'y':
            f.write(regex.sub(r'\3\2\1\4\5',line))
        else:
            f.write(line)

http://docs.python.org/tutorial/inputoutput.html

Sign up to request clarification or add additional context in comments.

1 Comment

Of course if you have a massive file that's too large to load into memory, then you could read a line at a time, and write to a temporary file instead.
0

Based on the help everyone provided, here's what I ended up going with:

#!/usr/bin/python

import re
import sys
import os

# regular expression
regex = re.compile(r'^([^&]*)(&)([^&]*)(&)([^&]*)')

# name of input and output files
if len(sys.argv)==1:
    print 'No file specified. Exiting.'
    sys.exit()
ifilename = sys.argv[1]
ofilename = ifilename+'.MODIFIED'

# read input file
ifile = open(ifilename)
lines = ifile.readlines()

ofile = open(ofilename,'w')

# prompt to make substitutions wherever a regex match occurs
for line in lines:
    match = regex.search(line)    
    if match is not None:
        print ''
        print '***CANDIDATE FOR SUBSTITUTION***'
        print '--:  '+line,
        print '++:  '+regex.sub(r'\3\2\1\4\5',line),
        print '********************************'
        input = raw_input('Make subsitution (enter y for yes)? ')
        if input == 'y':
            ofile.write(regex.sub(r'\3\2\1\4\5',line))
        else:
            ofile.write(line)
    else:
        ofile.write(line)

# replace original file with modified file
os.remove(ifilename)
os.rename(ofilename, ifilename)

Thanks a lot!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.