Chỉnh sửa dòng cụ thể trong tệp văn bản bằng Python


86

Giả sử tôi có một tệp văn bản chứa:

Dan
Warrior
500
1
0

Có cách nào để tôi có thể chỉnh sửa một dòng cụ thể trong tệp văn bản đó không? Ngay bây giờ tôi có cái này:

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

Vâng, tôi biết điều đó myfile.writelines('Mage')[1]là không chính xác. Nhưng bạn hiểu quan điểm của tôi, phải không? Tôi đang cố chỉnh sửa dòng 2 bằng cách thay thế Warrior bằng Mage. Nhưng tôi thậm chí có thể làm điều đó?


1
Tôi nghĩ bài này cover những gì bạn đang tìm kiếm: stackoverflow.com/questions/1998233/...
Kyle hoang dã

1
Nếu bạn phải làm những việc này nhiều, bạn có thể muốn xem xét việc chuyển đổi tệp này từ văn bản sang một cái gì đó như bdb hoặc bdb tương tự khác.
Nick Bastin

Câu trả lời:


123

Bạn muốn làm điều gì đó như sau:

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

Lý do cho điều này là bạn không thể làm điều gì đó như "thay đổi dòng 2" trực tiếp trong tệp. Bạn chỉ có thể ghi đè (không xóa) các phần của tệp - điều đó có nghĩa là nội dung mới chỉ bao gồm nội dung cũ. Vì vậy, nếu bạn viết 'Mage' trên dòng 2, dòng kết quả sẽ là 'Mageior'.


2
Chào Jochen, câu lệnh "with open (filename, mode)" cũng đóng tên tệp một cách ngầm định sau khi chương trình thoát khỏi nó, phải không?
Radu

@Gabriel Thx, điều quan trọng cần lưu ý, mặc dù tôi vẫn không sử dụng câu lệnh tệp with ... as. Pythonic hay không, tôi không thích nó :)
Radu

@Radu vấn đề là làm quen với nó. Tôi cũng đã từng đóng các tệp đã mở theo cách thủ công close.nhưng bây giờ tôi thấy rằng sử dụng withkhối gọn gàng hơn nhiều.
Gabriel

5
Có đúng không khi giả định, đây là một giải pháp được ưu tiên cho các tệp nhỏ? Nếu không, chúng tôi có thể cần rất nhiều bộ nhớ chỉ để lưu trữ dữ liệu. Hơn nữa, ngay cả với 1 lần chỉnh sửa, chúng ta cũng cần phải viết lại toàn bộ.
Arindam Roychowdhury

11
Thật tệ .. nếu bạn có tệp 20 Gb thì sao?
Brans Ds

21

bạn có thể sử dụng fileinput để chỉnh sửa tại chỗ

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

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

Và sau đó:

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

9
điều này sẽ tải toàn bộ nội dung của tệp vào bộ nhớ, điều này có thể không phải là một điều tốt nếu tệp lớn.
Steve Ng

@SteveNg bạn có giải pháp cho vấn đề bạn nhận thấy không? cả câu trả lời này và câu trả lời được chấp nhận đều dựa vào việc tải toàn bộ tệp trong bộ nhớ
Blupon

13

Bạn có thể làm điều đó theo hai cách, chọn những gì phù hợp với yêu cầu của bạn:

Phương pháp I.) Thay thế bằng cách sử dụng số dòng. Bạn có thể sử dụng chức năng tích hợp enumerate()trong trường hợp này:

Đầu tiên, ở chế độ đọc, lấy tất cả dữ liệu trong một biến

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

Thứ hai, ghi vào tệp (nơi liệt kê có tác dụng)

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)

Phương pháp II.) Sử dụng từ khóa bạn muốn thay thế:

Mở tệp ở chế độ đọc và sao chép nội dung vào danh sách

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" đã được thay thế bằng "Mage", vì vậy hãy ghi dữ liệu cập nhật vào tệp:

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

Đây là kết quả đầu ra trong cả hai trường hợp:

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

3

Nếu văn bản của bạn chỉ chứa một cá nhân:

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

Nếu văn bản của bạn chứa nhiều cá nhân:

nhập lại

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

Nếu “công việc” của một cá nhân có độ dài không đổi trong tin nhắn, bạn chỉ có thể thay đổi phần của tin nhắn tương ứng với “công việc” mà cá nhân mong muốn: đó là ý tưởng giống như ý tưởng của người gửi.

Nhưng theo tôi, tốt hơn là nên đặt các đặc điểm của các cá nhân trong một hệ tuần hoàn được ghi lại trong tệp với 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

2

Tôi đã thực hành làm việc trên các tệp tối nay và nhận ra rằng tôi có thể xây dựng dựa trên câu trả lời của Jochen để cung cấp chức năng tốt hơn cho việc sử dụng nhiều lần / nhiều lần. Thật không may, câu trả lời của tôi không giải quyết vấn đề xử lý các tệp lớn nhưng làm cho cuộc sống dễ dàng hơn trong các tệp nhỏ hơn.

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

0

Đây là cách dễ nhất để làm điều này.

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

Tôi hy vọng nó sẽ làm việc cho bạn.


-1

# đọc các dòng tệp và chỉnh sửa mục cụ thể

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

a = file.readlines ()

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

in (a)


1
Chào mừng bạn đến với Stack Overflow! Xin lưu ý rằng bạn đang trả lời một câu hỏi rất cũ và đã được trả lời. Đây là hướng dẫn về Cách trả lời .
help-info.de

-2

Giả sử tôi có một tệp có tên file_namenhư sau:

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

Chúng ta phải thay thế dòng 2 bằng "sửa đổi đã xong":

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.