2012-05-30 1840 views
6

Tengo el siguiente código, que modifica cada línea del archivo test.tex haciendo una sustitución de expresión regular.Escritura de Python al archivo usando stdout y 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), 

El único problema es que sólo quiero la sustitución de aplicar a determinadas líneas en el archivo, y no hay manera de definir un patrón para seleccionar las líneas correctas. Entonces, quiero mostrar cada línea e indicar al usuario en la línea de comando, preguntándole si debo hacer la sustitución en la línea actual. Si el usuario ingresa "y", se realiza la sustitución. Si el usuario simplemente no ingresa nada, la sustitución es no hecha.

El problema, por supuesto, es que al usar el código inplace=1 he redirigido efectivamente stdout al archivo abierto. Por lo tanto, no hay forma de mostrar la salida (por ejemplo, preguntando si hacer la sustitución) a la línea de comando que no se envía al archivo.

¿Alguna idea?

+2

Usar stderr ..... –

+0

'fileinput' no es la herramienta adecuada para este trabajo. Solo use un patrón estándar de lectura-modificación-escritura –

+0

@EliBendersky ¿me puede indicar un ejemplo de cómo hacer esa mención? Lo siento, soy muy nuevo en Python. – synaptik

Respuesta

3

El módulo de entrada de archivo es realmente para tratar con más de un archivo de entrada. En su lugar, puede utilizar la función open() regular.

Algo como esto debería funcionar.

Al leer el archivo y luego restablecer el puntero con seek(), podemos reemplazar el archivo en lugar de añadir a la final, y así modificar el archivo en el lugar

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

Por supuesto, si tiene un archivo masivo que es demasiado grande para cargar en la memoria, entonces puede leer una línea a la vez, y escribir en un archivo temporal en su lugar. –

+0

¡Muchas gracias! :) – synaptik

0

Based en la ayuda que todos brindaron, aquí es a lo que terminé yendo:

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

¡Muchas gracias!

Cuestiones relacionadas