2011-01-24 39 views
10

Tôi đang cố gắng thay thế văn bản trong một tệp văn bản bằng cách đọc từng dòng, kiểm tra, sau đó viết nếu cần phải cập nhật. Tôi KHÔNG muốn lưu dưới dạng tệp mới, vì tập lệnh của tôi đã sao lưu các tệp trước và hoạt động trên các bản sao lưu.cách thay thế (cập nhật) văn bản trong một dòng tệp theo dòng

Dưới đây là những gì tôi có cho đến nay ... tôi nhận được fpath từ os.walk() và tôi đảm bảo rằng var pathmatch trả về đúng:

fpath = os.path.join(thisdir, filename) 
with open(fpath, 'r+') as f: 
    for line in f.readlines(): 
     if '<a href="' in line: 
      for test in filelist: 
       pathmatch = file_match(line, test) 
        if pathmatch is not None: 
         repstring = filelist[test] + pathmatch 
         print 'old line:', line 
         line = line.replace(test, repstring) 
         print 'new line:', line 
         f.write(line) 

Nhưng những gì kết thúc xảy ra là tôi chỉ nhận được một vài dòng (cập nhật chính xác, nhớ bạn, nhưng lặp đi lặp lại từ trước đó trong tập tin) sửa chữa. Tôi nghĩ rằng đây là một vấn đề scoping, afaict.

* Ngoài ra: Tôi muốn biết cách chỉ thay thế văn bản khi trường hợp đầu tiên của kết quả phù hợp, ví dụ: tôi không muốn khớp với văn bản hiển thị, chỉ là href cơ bản.

+1

có bạn xem là chỉ đơn giản là sử dụng 'sed' để thay thế? – Amber

+0

http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 –

+0

@Amber: Theo cách khác. Tôi thực sự muốn kết thúc chuyện này và học sed sau. Tôi gần như đã hoàn thành việc này ... :) – jml

Trả lời

9

Trước tiên, bạn muốn viết dòng cho dù nó có khớp với mẫu hay không. Nếu không, bạn chỉ đang viết các dòng phù hợp.

Thứ hai, giữa việc đọc các dòng và ghi kết quả, bạn sẽ cần phải cắt bớt tệp (có thể f.seek(0) rồi f.truncate()) hoặc đóng bản gốc và mở lại. Chọn cựu, tôi muốn kết thúc với một cái gì đó như:

fpath = os.path.join(thisdir, filename) 
with open(fpath, 'r+') as f: 
    lines = f.readlines() 
    f.seek(0) 
    f.truncate() 
    for line in lines: 
     if '<a href="' in line: 
      for test in filelist: 
       pathmatch = file_match(line, test) 
        if pathmatch is not None: 
         repstring = filelist[test] + pathmatch 
         line = line.replace(test, repstring) 
     f.write(line) 
+0

rất hữu ích ... cảm ơn tấn. một điều kỳ lạ là nó dường như "gần như" làm việc lần đầu tiên và sau đó tôi chạy nó một lần nữa và nó không làm bất kỳ thay thế ... bất kỳ suy nghĩ? tôi có thể cố gắng theo dõi nó xuống ... – jml

+0

nevermind ... tôi đã tìm thấy vấn đề là gì. cám ơn rất nhiều!! – jml

+0

hi một lần nữa raph: tôi đã sửa đổi câu hỏi của tôi một chút-bạn sẽ được như vậy loại như để giải thích cho tôi làm thế nào để cập nhật mã để cho phép cho loại thay thế phù hợp duy nhất? cảm ơn ... – jml

9
  1. Mở tệp để đọc và sao chép tất cả các dòng vào bộ nhớ. Đóng tệp.
  2. Áp dụng các phép biến đổi của bạn trên các dòng trong bộ nhớ.
  3. Mở tệp để viết và ghi tất cả các dòng văn bản trong bộ nhớ.

with open(filename, "r") as f: 
    lines = (line.rstrip() for line in f) 
    altered_lines = [some_func(line) if regex.match(line) else line for line in lines] 
with open(filename, "w") as f: 
    f.write('\n'.join(altered_lines) + '\n') 
+0

cảm ơn vì đề nghị thay thế, nhưng tôi nghĩ rằng tôi thích giải pháp đầu tiên tốt hơn về nó phù hợp với nỗ lực của tôi. – jml

1

A (tương đối) cách an toàn để thay thế một dòng trong một tập tin.

#!/usr/bin/python 
# defensive programming style 
# function to replace a line in a file 
# and not destroy data in case of error 

def replace_line(filepath, oldline, newline): 
    """ 
    replace a line in a temporary file, 
    then copy it over into the 
    original file if everything goes well 

    """ 

# quick parameter checks 
    assert os.exists(filepath)   # ! 
    assert (oldline and str(oldline)) # is not empty and is a string 
    assert (newline and str(newline)) 

    replaced = False 
    written = False 

    try: 

    with open(filepath, 'r+') as f: # open for read/write -- alias to f  

     lines = f.readlines()   # get all lines in file 

     if oldline not in lines: 
      pass       # line not found in file, do nothing 

     else: 
     tmpfile = NamedTemporaryFile(delete=True) # temp file opened for writing 

     for line in lines:   # process each line 
      if line == oldline:  # find the line we want 
      tmpfile.write(newline) # replace it 
      replaced = True 
      else: 
      tmpfile.write(oldline) # write old line unchanged 

     if replaced:     # overwrite the original file  
      f.seek(0)     # beginning of file 
      f.truncate()     # empties out original file 

      for tmplines in tmpfile: 
      f.write(tmplines)   # writes each line to original file 
      written = True 

     tmpfile.close()    # tmpfile auto deleted  
     f.close()       # we opened it , we close it 

    except IOError, ioe:     # if something bad happened. 
    printf ("ERROR" , ioe) 
    f.close()       
    return False 

    return replaced and written  # replacement happened with no errors = True 

(lưu ý: đây thay thế toàn bộ dòng duy nhất, và tất cả các dòng phù hợp trong file)

Các vấn đề liên quan