Bearbeiten einer bestimmten Zeile in einer Textdatei in Python

85

Angenommen, ich habe eine Textdatei mit:

Dan
Warrior
500
1
0

Gibt es eine Möglichkeit, eine bestimmte Zeile in dieser Textdatei zu bearbeiten? Im Moment habe ich Folgendes:

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

Ja, ich weiß, dass myfile.writelines('Mage')[1]das falsch ist. Aber du verstehst, was ich meine, oder? Ich versuche, Zeile 2 zu bearbeiten, indem ich Warrior durch Mage ersetze. Aber kann ich das überhaupt tun?

Prüfung
quelle
1
Ich denke, dieser Beitrag behandelt, was Sie suchen: stackoverflow.com/questions/1998233/…
Kyle Wild
1
Wenn Sie so etwas häufig tun müssen, sollten Sie diese Datei von Text in etwas wie bdb oder ein anderes bdb-ähnliches konvertieren.
Nick Bastin

Antworten:

123

Sie möchten so etwas tun:

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

Der Grund dafür ist, dass Sie so etwas wie "Zeile 2 ändern" nicht direkt in einer Datei ausführen können. Sie können nur Teile einer Datei überschreiben (nicht löschen) - das bedeutet, dass der neue Inhalt nur den alten Inhalt abdeckt. Wenn Sie also "Magier" über Zeile 2 schreiben, lautet die resultierende Zeile "Magier".

Jochen Ritzel
quelle
2
Hallo Jochen, die Anweisung "with open (Dateiname, Modus)" schließt den Dateinamen auch implizit, nachdem das Programm ihn beendet hat, oder?
Radu
@ Gabriel Thx, das ist wichtig zu beachten, obwohl ich das with ... immer noch nicht als Dateianweisung verwende. Pythonic oder nicht, ich mag es nicht :)
Radu
@Radu es ist eine Frage der Gewöhnung. Früher habe ich geöffnete Dateien auch manuell über geschlossen, close.aber jetzt sehe ich, dass die Verwendung eines withBlocks viel sauberer ist.
Gabriel
5
Ist es richtig anzunehmen, dass dies eine Lösung ist, die für kleine Dateien bevorzugt wird? Andernfalls benötigen wir möglicherweise viel Speicher, um die Daten zu speichern. Darüber hinaus müssen wir auch für 1 Bearbeitung das Ganze noch einmal schreiben.
Arindam Roychowdhury
11
Schlecht .. was ist, wenn Sie 20-GB-Datei haben?
Brans Ds
21

Sie können die Dateieingabe verwenden, um die Bearbeitung an Ort und Stelle durchzuführen

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

Und dann:

replace_line('stats.txt', 0, 'Mage')
Peter C.
quelle
9
Dies würde den gesamten Inhalt der Datei in den Speicher laden, was möglicherweise nicht gut ist, wenn die Datei sehr groß ist.
Steve Ng
@SteveNg Haben Sie eine Lösung für das Problem, das Sie bemerkt haben? Sowohl diese als auch die akzeptierte Antwort
hängen
13

Sie können dies auf zwei Arten tun: Wählen Sie aus, was Ihren Anforderungen entspricht:

Methode I.) Ersetzen mit Zeilennummer. enumerate()In diesem Fall können Sie die integrierte Funktion verwenden :

Holen Sie sich im Lesemodus zunächst alle Daten in eine Variable

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

Zweitens schreiben Sie in die Datei (wo die Aufzählung zum Handeln kommt)

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)

Methode II.) Verwenden Sie das Schlüsselwort, das Sie ersetzen möchten:

Öffnen Sie die Datei im Lesemodus und kopieren Sie den Inhalt in eine Liste

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.  

"Warrior" wurde durch "Mage" ersetzt. Schreiben Sie die aktualisierten Daten in die Datei:

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

Dies ist die Ausgabe in beiden Fällen:

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

Wenn Ihr Text nur eine Person enthält:

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

Wenn Ihr Text mehrere Personen enthält:

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

Wenn der „Job“ einer Person im Text eine konstante Länge hat, können Sie nur den Teil des Texts ändern, der dem „Job“ der gewünschten Person entspricht: Das ist die gleiche Idee wie die des Absenders.

Aber meiner Meinung nach wäre es besser, die Merkmale von Personen in ein Wörterbuch zu schreiben, das in einer Datei mit cPickle aufgezeichnet ist:

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
quelle
2

Ich habe heute Abend geübt, an Dateien zu arbeiten, und festgestellt, dass ich auf Jochens Antwort aufbauen kann, um mehr Funktionen für die wiederholte / mehrfache Verwendung bereitzustellen. Leider geht meine Antwort nicht auf das Problem des Umgangs mit großen Dateien ein, sondern erleichtert das Leben in kleineren Dateien.

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))
Sie nicht
quelle
0

Dies ist der einfachste Weg, dies zu tun.

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

Ich hoffe es wird für dich funktionieren.

Rohit Nishad
quelle
-1

#Lesen Sie die Dateizeilen und bearbeiten Sie ein bestimmtes Element

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

a = file.readlines ()

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

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

print (a [0])

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

file.writelines (a)

file.close ()

drucken (a)

Ajay Jaiswal
quelle
1
Willkommen bei Stack Overflow! Bitte beachten Sie, dass Sie eine sehr alte und bereits beantwortete Frage beantworten. Hier ist eine Anleitung zur Beantwortung .
help-info.de
-2

Angenommen, ich habe eine Datei file_namemit folgendem Namen:

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

Wir müssen Zeile 2 durch "Änderung ist abgeschlossen" ersetzen:

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
quelle