Editando uma linha específica no arquivo de texto em Python

86

Digamos que eu tenha um arquivo de texto contendo:

Dan
Warrior
500
1
0

Existe uma maneira de editar uma linha específica nesse arquivo de texto? Agora eu tenho isso:

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

Sim, eu sei que isso myfile.writelines('Mage')[1]está incorreto. Mas você me entende, certo? Estou tentando editar a linha 2 substituindo Warrior por Mage. Mas eu posso fazer isso?

teste
fonte
1
Acho que esta postagem cobre o que você está procurando: stackoverflow.com/questions/1998233/…
Kyle Wild
1
Se você tem que fazer muito esse tipo de coisa, talvez queira converter esse arquivo de texto para algo como bdb ou outro semelhante.
Nick Bastin

Respostas:

123

Você quer fazer algo assim:

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

A razão para isso é que você não pode fazer algo como "alterar a linha 2" diretamente em um arquivo. Você só pode substituir (não excluir) partes de um arquivo - isso significa que o novo conteúdo cobre apenas o conteúdo antigo. Então, se você escreveu 'Mage' na linha 2, a linha resultante seria 'Mageior'.

Jochen Ritzel
fonte
2
Olá Jochen, a declaração "com abrir (nome do arquivo, modo)" também fecha o nome do arquivo implicitamente após o programa sair dele, certo?
Radu
@Gabriel Thx, isso é importante observar, embora eu ainda não use o comando with ... as file. Pythônico ou não, eu não gosto :)
Radu
@Radu é questão de se acostumar. Eu também costumava fechar os arquivos abertos manualmente via, close.mas agora vejo que usar um withbloco é muito mais limpo.
Gabriel,
5
É correto supor que esta é uma solução preferida para arquivos pequenos? Caso contrário, podemos precisar de muita memória apenas para armazenar os dados. Além disso, mesmo para 1 edição, precisamos escrever tudo novamente.
Arindam Roychowdhury
11
Ruim .. e se você tiver um arquivo de 20 Gb?
Brans Ds
21

você pode usar o arquivo de entrada para fazer a edição no local

import fileinput
for  line in fileinput.FileInput("myfile", inplace=1):
    if line .....:
         print line
ghostdog74
fonte
19
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()

E depois:

replace_line('stats.txt', 0, 'Mage')
Peter C
fonte
9
isso carregaria todo o conteúdo do arquivo na memória, o que pode não ser bom se o arquivo for muito grande.
Steve Ng
@SteveNg você tem uma solução para o problema que percebeu? tanto esta resposta quanto a aceita dependem do carregamento de todo o arquivo na memória
Blupon
13

Você pode fazer isso de duas maneiras, escolha o que se adapta às suas necessidades:

Método I.) Substituindo usando o número da linha. Você pode usar a função integrada enumerate()neste caso:

Primeiro, em modo de leitura, obtenha todos os dados em uma variável

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

Em segundo lugar, escreva no arquivo (onde enumerar entra em ação)

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.) Usando a palavra-chave que você deseja substituir:

Abra o arquivo em modo de leitura e copie o conteúdo para uma 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.  

"Guerreiro" foi substituído por "Mago", então grave os dados atualizados no arquivo:

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

Este é o resultado em ambos os casos:

Dan                   Dan           
Warrior   ------>     Mage       
500                   500           
1                     1   
0                     0           
Aseem Yadav
fonte
3

Se o seu texto contém apenas uma pessoa:

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

Se o seu texto contém várias pessoas:

importar 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()

Se o “trabalho” de um indivíduo tivesse um comprimento constante no texto, você poderia alterar apenas a parte do texto correspondente ao “trabalho” do indivíduo desejado: essa é a mesma ideia do remetente.

Mas, a meu ver, melhor seria colocar as características dos indivíduos em um dicionário gravado em arquivo com 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
eyquem
fonte
2

Tenho praticado o trabalho com arquivos esta noite e percebi que posso desenvolver a resposta de Jochen para fornecer maior funcionalidade para uso repetido / múltiplo. Infelizmente, minha resposta não aborda a questão de lidar com arquivos grandes, mas facilita a vida em arquivos menores.

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))
eles não
fonte
0

Esta é a maneira mais fácil de fazer isso.

fin = open("a.txt")
f = open("file.txt", "wt")
for line in fin:
    f.write( line.replace('foo', 'bar') )
fin.close()
f.close()

Espero que funcione para você.

Rohit Nishad
fonte
-1

#read linhas de arquivo e editar item específico

file = open ("pythonmydemo.txt", 'r')

a = file.readlines ()

imprimir (a [0] [6:11])

a [0] = a [0] [0: 5] + 'Ericsson \ n'

imprimir (a [0])

file = open ("pythonmydemo.txt", 'w')

file.writelines (a)

file.close ()

imprimir (a)

Ajay Jaiswal
fonte
1
Bem-vindo ao Stack Overflow! Observe que você está respondendo a uma pergunta muito antiga e já respondida. Aqui está um guia sobre como responder .
help-info.de
-2

Suponha que eu tenha um arquivo com file_nameo seguinte nome :

this is python
it is file handling
this is editing of line

Temos que substituir a linha 2 por "modificação concluída":

f=open("file_name","r+")
a=f.readlines()
for line in f:
   if line.startswith("rai"):
      p=a.index(line)
#so now we have the position of the line which to be modified
a[p]="modification is done"
f.seek(0)
f.truncate() #ersing all data from the file
f.close()
#so now we have an empty file and we will write the modified content now in the file
o=open("file_name","w")
for i in a:
   o.write(i)
o.close()
#now the modification is done in the file
Shivam Rai
fonte