簡體   English   中英

基於 Python 的腳本,用於從文件中刪除在另一個文件中顯示的行

[英]Python-based script to delete lines from file, that presented in another file

我有一個文件all_projects.txt ,其中包含:

java/my_project_wwe
java/my_project_wwf
java/my_project_wcw
net/my_project_aew
net/my_project_impact
net/my_project_njpw

我有另一個文件project_to_delete.txt ,其中包含:

java/my_project_wcw
net/my_project_njpw

結果,我想收到:

java/my_project_wwe
java/my_project_wwf
net/my_project_aew
net/my_project_impact

它通過 bash 完美運行:
grep -v -x -f project_to_delete.txt all_projects.txt
但我想通過 python 來實現。 當然,我們可以做類似模塊 os.system 或os.system類的subprocess ,但我正在尋找的不是。 我試圖這樣做:

with open('all_projects.txt','r') as read1:
  f1 = read1.readlines()

with open('project_to_delete.txt', 'r') as read2:
  f2 = read2.readlines()

with open('result.txt', 'w+') as write1:
  for line in f1:
    if line in f2:
      write1.write(line + '\n')

但在result.txt中,我有:

java/my_project_wcw

net/my_project_njpw

我哪里有錯誤?
感謝您的關注,感謝您的幫助。

您的 if 條件不正確。 您會在 f1 和 f2 中找到相同的行。 你的 if 條件應該是if line not in f2

with open('result.txt', 'w+') as write1:
    for line in f1:
        if line not in f2:  #Nottice the not here
            write1.write(line + '\n')

@Saad_Khan 的回答是正確的,但我只是想就您的問題提出一個觀點,每當我閱讀這樣的問題時,我都會試圖強調這一點,這是關於數據抽象的觀點。

您編寫問題的方式是關於“刪除文件中的行”與“另一個文件中的行”相同。 但是你的問題真的那么依賴於文件嗎? 在這種情況下可能有點,因為您提到對grep做同樣的事情,而像grep這樣的命令行實用程序往往是面向文件/流的。

但是在像 Python 這樣的編程語言中,您可能會嘗試少考慮“文件”,而多考慮這些文件中序列化的數據結構。 在這種情況下,只是字符串列表。

所以你的問題變成了,如何區分兩個字符串列表? 因為您最初編寫問題的方式只是使用readlines()將文件的全部內容讀取到列表中(如果您正在迭代大文件,問題可能會有所不同,但差別不大)。

那么如何區分兩個列表呢?

一種簡單的方法是使用set.difference

>>> list_a = [1, 2, 3, 4, 5]
>>> list_b = [3, 5, 6]
>>> set_c = set(list_a).difference(list_b)
>>> set_c
set([1, 2, 4])

由於set不能保證被訂購,如果您希望 output 是可預測的,您可以對 output 進行排序:

>>> list_c = sorted(set_c)

但是,更常見的模式更像@Saad_Khan 的答案,它保留了 list a的原始順序; 您可以使用以下列表理解來執行此操作:

>>> list_c = [s for s in list_a if s not in list_b]

但是,這可能會有點慢,因為如果list_b很大,它必須在每個循環中對list_b的每個元素(在最壞的情況下)執行字符串比較。 所以更常見的模式是將list_b變成一個set

>>> set_b = set(list_b)
>>> list_c = [s for s in list_a if s not in set_b]

這樣做的好處是每個if s not in set_b都有 O(1) 行為,而if s not in list_blist_b的大小有 O(n) 行為。

既然您的工具帶中有這些更通用的技術,那么擔心如何處理結果是一個完全獨立於讀/寫文件的問題。

給定list_c您現在可以以任何方式自由地將其寫入第三個文件。 或者,如果您想編寫像grep之類的命令行實用程序,有時只需調用print()並允許用戶使用 shell 重定向(如果他們想要將 Z78E6221F6393D1356681DB398F1DB398F1 結果重定向到文件:DZCE4

>>> print('\n'.join(list_c))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM