2011-01-18 13 views
39

Digamos que tengo un archivo de texto que contiene:Edición línea específica en el archivo de texto en Python

Dan 
Warrior 
500 
1 
0 

¿Hay alguna manera de modificar una línea específica en ese archivo de texto? En este momento tengo esto:

#!/usr/bin/env python 
import io 

myfile = open('stats.txt', 'r') 
dan = myfile.readline() 
print dan 
print "Your name: " + dan.split('\n')[0] 

try: 
    myfile = open('stats.txt', 'a') 
    myfile.writelines('Mage')[1] 
except IOError: 
     myfile.close() 
finally: 
     myfile.close() 

Sí, sé que myfile.writelines('Mage')[1] es incorrecto. Pero entiendes mi punto, ¿verdad? Estoy intentando editar la línea 2 reemplazando a Warrior con Mage. ¿Pero puedo incluso hacer eso?

+1

Creo que este post cubre lo que estás buscando: http://stackoverflow.com/questions/1998233/replace-string-in-a-specific-line-using-python –

+1

Si usted tiene que Haga mucho este tipo de cosas, es posible que desee considerar la conversión de este archivo de texto a algo así como bdb u otro bdb-similar. –

Respuesta

59

que quiere hacer algo como esto:

# with is like your try .. finally block in this case 
with open('stats.txt', 'r') as file: 
    # read a list of lines into data 
    data = file.readlines() 

print data 
print "Your name: " + data[0] 

# now change the 2nd line, note that you have to add a newline 
data[1] = 'Mage\n' 

# and write everything back 
with open('stats.txt', 'w') as file: 
    file.writelines(data) 

La razón de esto es que no se puede hacer algo así como "cambiar la línea 2" directamente en un archivo. Solo puede sobrescribir (no eliminar) partes de un archivo; eso significa que el nuevo contenido solo cubre el contenido anterior. Entonces, si escribió 'Mage' sobre la línea 2, la línea resultante sería 'Mageior'.

+2

Hola Jochen, la frase "with open (filename, mode)" también cierra el nombre de archivo implícitamente después de que el programa lo abandona, ¿no? – Radu

+1

@Radu sí lo hace. – Gabriel

+0

@Gabriel Thx, eso es importante tener en cuenta, aunque todavía no uso el con ... como declaración de archivo. Pythonic o no, no me gusta :) – Radu

9
def replace_line(file_name, line_num, text): 
    lines = open(file_name, 'r').readlines() 
    lines[line_num] = text 
    out = open(file_name, 'w') 
    out.writelines(lines) 
    out.close() 

Y luego:

replace_line('stats.txt', 0, 'Mage') 
+2

esto cargaría todo el contenido del archivo en la memoria, lo que podría no ser bueno si el archivo es enorme. –

+0

muy buena solución! – Konstantin

13

puede utilizar fileinput que ver en la edición lugar

import fileinput 
for line in fileinput.FileInput("myfile", inplace=1): 
    if line .....: 
     print line 
2

Si el texto contiene un solo individuo:

import re 

# creation 
with open('pers.txt','wb') as g: 
    g.write('Dan \n Warrior \n 500 \r\n 1 \r 0 ') 

with open('pers.txt','rb') as h: 
    print 'exact content of pers.txt before treatment:\n',repr(h.read()) 
with open('pers.txt','rU') as h: 
    print '\nrU-display of pers.txt before treatment:\n',h.read() 


# treatment 
def roplo(file_name,what): 
    patR = re.compile('^([^\r\n]+[\r\n]+)[^\r\n]+') 
    with open(file_name,'rb+') as f: 
     ch = f.read() 
     f.seek(0) 
     f.write(patR.sub('\\1'+what,ch)) 
roplo('pers.txt','Mage') 


# after treatment 
with open('pers.txt','rb') as h: 
    print '\nexact content of pers.txt after treatment:\n',repr(h.read()) 
with open('pers.txt','rU') as h: 
    print '\nrU-display of pers.txt after treatment:\n',h.read() 

Si su el texto contiene varias personas:

import re

# creation 
with open('pers.txt','wb') as g: 
    g.write('Dan \n Warrior \n 500 \r\n 1 \r 0 \n Jim \n dragonfly\r300\r2\n10\r\nSomo\ncosmonaut\n490\r\n3\r65') 

with open('pers.txt','rb') as h: 
    print 'exact content of pers.txt before treatment:\n',repr(h.read()) 
with open('pers.txt','rU') as h: 
    print '\nrU-display of pers.txt before treatment:\n',h.read() 


# treatment 
def ripli(file_name,who,what): 
    with open(file_name,'rb+') as f: 
     ch = f.read() 
     x,y = re.search('^\s*'+who+'\s*[\r\n]+([^\r\n]+)',ch,re.MULTILINE).span(1) 
     f.seek(x) 
     f.write(what+ch[y:]) 
ripli('pers.txt','Jim','Wizard') 


# after treatment 
with open('pers.txt','rb') as h: 
    print 'exact content of pers.txt after treatment:\n',repr(h.read()) 
with open('pers.txt','rU') as h: 
    print '\nrU-display of pers.txt after treatment:\n',h.read() 

Si el “trabajo” de un individuo era de una longitud constante en el texte, puede cambiar sólo la parte de texte correspondiente al “trabajo” del individuo deseada: que es la misma idea que Senderle.

Pero en mi opinión, mejor habría que poner las características de los individuos en una dictionnary registrada en archivo con cPickle:

from cPickle import dump, load 

with open('cards','wb') as f: 
    dump({'Dan':['Warrior',500,1,0],'Jim':['dragonfly',300,2,10],'Somo':['cosmonaut',490,3,65]},f) 

with open('cards','rb') as g: 
    id_cards = load(g) 
print 'id_cards before change==',id_cards 

id_cards['Jim'][0] = 'Wizard' 

with open('cards','w') as h: 
    dump(id_cards,h) 

with open('cards') as e: 
    id_cards = load(e) 
print '\nid_cards after change==',id_cards 
1

usted puede hacerlo de dos maneras, elegir lo que se adapte a sus necesidades:

Método I.) Reemplazando usando el número de línea. Puede utilizar la función incorporada de enumerate() en este caso:

primer lugar, en modo de lectura obtener todos los datos en una variable

with open("your_file.txt",'r') as f: 
    get_all=f.readlines() 

En segundo lugar, escribir en el fichero (donde enumerar viene a la acción)

with open("your_file.txt",'w') as f: 
    for i,line in enumerate(get_all,1):   ## STARTS THE NUMBERING FROM 1 (by default it begins with 0)  
     if i == 2:        ## OVERWRITES line:2 
      f.writelines("Mage\n") 
     else: 
      f.writelines(line) 

Método II.) El uso de la palabra clave que desea reemplazar:

Abrir el archivo en modo de lectura y copiar el contenido a una lista

with open("some_file.txt","r") as f: 
    newline=[] 
    for word in f.readlines():   
     newline.append(word.replace("Warrior","Mage")) ## Replace the keyword while you copy. 

"Guerrero" se ha sustituido por "Mago", por lo que escribir la actualización los datos en el fichero:

with open("some_file.txt","w") as f: 
    for line in newline: 
     f.writelines(line) 

Esto es lo que la salida de será en ambos casos:

Dan     Dan   
Warrior ------>  Mage  
500     500   
1      1 
0      0   
0

He estado practicando trabajando en archivos esta tarde y me di cuenta de que puedo basarme en la respuesta de Jochen para proporcionar una mayor funcionalidad para uso repetido/múltiple. Lamentablemente, mi respuesta no aborda el problema de tratar con archivos de gran tamaño, pero hace la vida más fácil en archivos más pequeños.

with open('filetochange.txt', 'r+') as foo: 
    data = foo.readlines()     #reads file as list 
    pos = int(input("Which position in list to edit? "))-1 #list position to edit 
    data.insert(pos, "more foo"+"\n")   #inserts before item to edit 
    x = data[pos+1] 
    data.remove(x)      #removes item to edit 
    foo.seek(0)      #seeks beginning of file 
    for i in data: 
     i.strip()     #strips "\n" from list items 
     foo.write(str(i)) 
Cuestiones relacionadas