2012-05-30 6 views
6

Ich habe den folgenden Code, der jede Zeile der Datei test.tex durch eine regelmäßige Ausdrucksersetzung ändert.Python Schreiben in Datei mit stdout und fileinput

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), 

Das einzige Problem ist, dass ich nur die Substitution will auf bestimmte Zeilen in der Datei anzuwenden, und es gibt keine Möglichkeit, ein Muster zu definieren, die richtigen Linien zu wählen. Daher möchte ich jede Zeile anzeigen und den Benutzer in der Befehlszeile auffordern zu fragen, ob die Ersetzung an der aktuellen Zeile vorgenommen werden soll. Wenn der Benutzer "y" eingibt, wird die Ersetzung vorgenommen. Wenn der Benutzer einfach nichts eingibt, wird die Ersetzung nicht vorgenommen.

Das Problem ist natürlich, dass durch die Verwendung des Codes inplace=1 ich stdout effektiv auf die geöffnete Datei umgeleitet habe. Es gibt also keine Möglichkeit, die Ausgabe anzuzeigen (z. B. zu fragen, ob die Ersetzung durchgeführt werden soll), die nicht an die Datei gesendet wird.

Irgendwelche Ideen?

+2

Verwenden Sie stderr ..... –

+0

'Fileinput' ist nicht das richtige Werkzeug für diesen Job. Verwenden Sie einfach ein Standard-Read-Modify-Write-Muster –

+0

@EliBendersky können Sie mich auf ein Beispiel zu tun, was die Erwähnung? Entschuldigung, ich bin sehr neu bei Python. – synaptik

Antwort

3

Das Dateieingabemodul ist wirklich für den Umgang mit mehr als einer Eingabedatei gedacht. Sie können stattdessen die reguläre Funktion open() verwenden.

So etwas sollte funktionieren.

Durch Lesen der Datei dann den Zeiger zurückzusetzen mit seek(), können wir die Datei überschreiben, anstatt am Ende angehängt, und so bearbeiten, dass die Datei 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

+2

Natürlich, wenn Sie eine große Datei haben, die zu groß ist, um sie in den Speicher zu laden, können Sie Zeile für Zeile lesen und stattdessen in eine temporäre Datei schreiben. –

+0

Vielen Dank! :) – synaptik

0

Based auf die Hilfe, die alle zur Verfügung gestellt, hier ist, was ich ging mit:

#!/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) 

Vielen Dank!