2013-05-17 222 views
1

我正在嘗試更改文本文件中的某些行而不影響其他行。這是所謂「的text.txt」的文本文件中讀取/寫入文本文件

this is a test1|number1 
this is a test2|number2 
this is a test3|number2 
this is a test4|number3 
this is a test5|number3 
this is a test6|number4 
this is a test7|number5 
this is a test8|number5 
this is a test9|number5 
this is a test10|number5 

我的目標是改變行4和第5行,但保持休息一樣。

mylist1=[] 
for lines in open('test','r'): 
    a=lines.split('|') 
    b=a[1].strip() 
    if b== 'number3': 
     mylist1.append('{}|{} \n'.format('this is replacement','number7')) 
    else: 
     mylist1.append('{}|{} \n'.format(a[0],a[1].strip())) 
myfile=open('test','w') 
myfile.writelines(mylist1) 

即使代碼正常工作,我想知道是否有更好的和有效的方法來做到這一點?是否可以通過行號讀取文件?

+0

你不能寫在任意位置「中的線」,但如果你想知道在讀取當前行號時,可以使用'enumerate',如'in for index,enumerate中的行(open('test','r')):'。如果你真的想通過數字而不是位置來識別線條,這可能會有所幫助。順便說一句:像你這樣寫'for __lines__'會引起誤解 - 你每次在循環中得到的是一個__single__行。 – kampu

回答

10

沒有太多可以改進的地方。但是您必須將所有行寫入新文件,無論是更改還是更改。小的改進是:

  • 使用with聲明;
  • 避免在列表中存儲行;
  • 書寫lines沒有格式在else子句(如果適用)。

應用上述所有的:

import shutil 
with open('test') as old, open('newtest', 'w') as new: 
    for line in old: 
     if line.rsplit('|', 1)[-1].strip() == 'number3': 
      new.write('this is replacement|number7\n') 
     else: 
      new.write(line) 
shutil.move('newtest', 'test') 
+0

你說得對。也許他可以使用內存中的文件(模塊StringIO)或臨時文件(模塊tempfile),但基本上他無法對原始文件進行任何操作。 – Markon

+0

爲什麼當我將「newtest」更改爲「test」時,這不起作用?即使我必須重寫來修改文件,我仍然需要它具有相同的名稱。但非常感謝幫助 –

+0

@ChrisAung因爲在寫模式下打開文件會截斷它。您立即丟失舊內容。所以你應該在完成時移動文件(參見我的編輯),或者使用'fileinput'作爲@jamylak提示;但是如果你看看文檔,'fileinput'在內部也是這樣做的:創建一個備份文件,然後靜靜地刪除它。 –

2

編號文件是面向字節的,而不是面向行的,並且改變行的長度不會超前後續字節。

3
import fileinput 

for lines in fileinput.input('test', inplace=True): 
    # inplace=True redirects stdout to a temp file which will 
    # be renamed to the original when we reach the end of the file. this 
    # is more efficient because it doesn't save the whole file into memeory 
    a = lines.split('|') 
    b = a[1].strip() 
    if b == 'number3': 
     print '{}|{} '.format('this is replacement', 'number7') 
    else: 
     print '{}|{} '.format(a[0], a[1].strip()) 
0

嘗試此解決方案

with open('test', inplace=True) as text_file: 
    for line in text_file: 
     if line.rsplit('|', 1)[-1].strip() == 'number3': 
      print '{}|{} \n'.format('this is replacement', 'number7') 
     else: 
      print line 
0

這不是完全清楚你的意圖是否是確定的線路由他們替代值,或其行號

如果是前者你的意圖, 你可以得到這樣的行的列表:

with open('test','r') as f: 
    oldlines = f.read().splitlines() 

如果有尾隨空白的危險,你還可以:

然後你就可以對其進行處理像這樣:

newlines = [ line if not line.strip().endswith('|number3') else 'this is replacement|number7' for line in oldlines] 

打開目標文件(我假設你想覆蓋原來,在這裏),並寫出所有行:

with open('test','w') as f: 
    f.write("\n".join(newlines)) 

這是一種通用模式,可用於任何類型的簡單線路過濾。

如果你的意思是,以確定由數行,你可以只改變「新行」行:

newlines = [ line if i not in (3, 4) else 'this is replacement|number7' for i, line in enumerate(oldlines)]