Editing specific line in text file in python

2019-01-01 11:50发布

问题:

Let\'s say I have a text file containing:

Dan
Warrior
500
1
0

Is there a way I can edit a specific line in that text file? Right now I have this:

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

Yes, I know that myfile.writelines(\'Mage\')[1] is incorrect. But you get my point, right? I\'m trying to edit line 2 by replacing Warrior with Mage. But can I even do that?

回答1:

You want to do something like this:

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

The reason for this is that you can\'t do something like \"change line 2\" directly in a file. You can only overwrite (not delete) parts of a file - that means that the new content just covers the old content. So, if you wrote \'Mage\' over line 2, the resulting line would be \'Mageior\'.



回答2:

you can use fileinput to do in place editing

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


回答3:

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

And then:

replace_line(\'stats.txt\', 0, \'Mage\')


回答4:

If your text contains only one individual:

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

If your text contains several individuals:

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

If the “job“ of an individual was of a constant length in the texte, you could change only the portion of texte corresponding to the “job“ the desired individual: that’s the same idea as senderle’s one.

But according to me, better would be to put the characteristics of individuals in a dictionnary recorded in file with 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


回答5:

You can do it in two ways, choose what suits your requirement:

Method I.) Replacing using line number. You can use built-in function enumerate() in this case:

First, in read mode get all data in a variable

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

Second, write to the file (where enumerate comes to action)

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)

Method II.) Using the keyword you want to replace:

Open file in read mode and copy the contents to a list

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\" has been replaced by \"Mage\", so write the updated data to the file:

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

This is what the output will be in both cases:

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


回答6:

I have been practising working on files this evening and realised that I can build on Jochen\'s answer to provide greater functionality for repeated/multiple use. Unfortunately my answer does not address issue of dealing with large files but does make life easier in smaller files.

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


标签: python io