2016-11-19 44 views
0

我有三個列表:filePath,textToFind,textToReplace。我需要在給定的filePath中打開每個文件,找到一行並替換一行。列表總是按順序排列,並且長度始終相同。下面的代碼:如何在Python中多次查找並替換行只有一次

for i, path in enumerate(filePath): 
    for line in fileinput.input(path, inplace=1): 
     sys.stdout.write(line.replace(textToFind[i], textToReplace[i])) 

的問題是可以的textToFind在文件中可以找到無數次,所以這段代碼替換它與textToReplace當前索引位置找到的文本的所有匹配。我需要它在第一次找到該項目時中斷,然後繼續下一次迭代。我怎樣才能做到這一點?

+0

你的意思是說,你想在'textToFind中'和''的textToFind相應的索引條目filePath'的'在每個索引處替換文件?或者,在'filePath'中存在的所有文件中'textToFind'的所有條目都含有'textToFind'? –

+0

第一個。我想用textToFind和textToReplace中的相應索引替換filePath的每個索引。 filePath和textToFind並不總是唯一的,但textToReplace總是唯一的。 – pgtips

回答

2

您需要檢測何時需要更換。如果找到,標誌,但繼續寫下其餘的行或者你會截斷文件。

(注意,在3列出了使用zip避免攜帶索引)

for path,find,replace in zip(filePath,textToFind,textToReplace):  
    match_found = False 
    for line in fileinput.input(path, inplace=1): 
     if match_found: 
     # keep writing the rest of lines, unchanged 
     sys.stdout.write(line) 
     else: 
     # try to replace 
     rep = line.replace(find, replace) 
     sys.stdout.write(rep) 
     if line!=rep: 
      # flag: don't replace anything till the end 
      match_found = True 

編輯:後另一個答案的作者小的討論,我認爲他的2個循環模式比1更好國旗,所以我借了它,節省了對國旗的需求,必須稍微快一點:

for path,find,replace in zip(filePath,textToFind,textToReplace): 
    handle = fileinput.input(path, inplace=1) 
    for line in handle: 
    rep = line.replace(find, replace) 
    sys.stdout.write(rep) 
    if line!=rep: 
     break 
    for line in handle: 
     sys.stdout.write(line) 
+0

完美的作品,非常感謝你! – pgtips

2

我的解決方案已經大大減少了優雅。不過,我仍然想提供一個臨時文件的替代方案。

# loop over every path, thing to find and replacement in the lists 
for path, needle, replacement in zip(filePath, textToFind, textToReplace): 
    with open(path) as read_handle: 
     with open(path + '.tmp', 'w+') as write_handle: 
      # first print and replace 
      for line in read_handle: 
       write_handle.write(line.replace(needle, replacement)) 

       # if we found something 
       if needle in line: 
        break # quit this the inner for-loop 

      # the remaining lines should be printed without modification 
      for line in read_handle: 
        write_handle.write(line) 
    # overwrite the file with the temporary file 
    shutil.move(path + '.tmp', path) 
+0

這不是寫回文件 –

+0

誤解了文件輸入api,你是對的。 –

+1

我喜歡你不使用標誌的優雅方式,只需打破第一個替換循環,並簡單地迭代到最後。我會編輯你的答案,以便回答問題。 –

0

作爲回答您的實際問題:

「如何查找和Python中發現多次更換時行僅一次」

str.replace()有一個可選的maxreplace選項,該選項限制要替換的發生次數。由於每document

與string.replace(S,舊,新[,maxreplace])

返回字符串s的子串用舊的換成新出現的所有副本。 如果給出可選參數maxreplace,則會替換第一個maxreplace事件。

例如:

>>> my_test_string = 'Hello Hello Hello' 

#           v maxreplace as `1` 
>>> my_test_string.replace('Hello', 'World', 1) 
'World Hello Hello' 
#^Only first word is replaced 
相關問題