如何取得第一個文件中包含的不是 i 的名稱?

如何取得第一個文件中包含的不是 i 的名稱?

我有兩個文件,其中包含數十億個 DNA 序列名稱,第二個文件是第一個文件的真子集:

例如,

1°:john mike anna paul laura .... 

2°:john mike paul ...

所有名稱佔一行。

我的問題是,如何取得第一個文件中包含但第二個文件中不包含的名稱?

謝謝大家!

答案1

這很簡單,但如果每行只有一個名稱而不是空格分隔的列表,您的生活會容易得多。 Linux 中有許多用於操作文字檔案的優秀實用程序,這是所有 *nixes 都擅長的事情之一,但大多數人期望每行一個專案。因此,我的大多數解決方案將從相應地修改文件開始。

將文件更改為每行一個名稱:

sed 's/ /\n/g' file > newfile

或者,修改原始文件

sed -i 's/ /\n/g' file

一旦你這樣做了,其中任何一個都會給你你想要的:

  1. grep

    $ grep -vFwf file2 file1
    anna
    laura
    
  2. comm或者diff

    $ comm -23 <(sort file1) <(sort file2)
    anna
    laura
    
    
    $ diff file1 file2 | grep -Po '<\s+\K.*'
    anna
    laura
    
  3. awk

    $ awk '(NR==FNR){a[$1]++; next}!($1 in a){print}' file2 file1 
    laura
    anna
    
  4. 珀爾

    $ perl -lne 'BEGIN{open(A,"file2"); while(<A>){chomp; $k{$_}++}} print unless $k{$_}' file2 file1
    laura
    anna
    

    或者

    $ perl -lne '$k{$_}++; END{map{print unless $k{$_}>1}keys(%k)}' file2 file1
    laura
    anna
    

如果您確實不想更改文件的格式(但實際上您應該這樣做),您可以執行類似的操作

awk '{for (i=1;i<=NF;i++){a[$i]++}}END{for(n in a){if(a[n]<2){print n}}}' file2 file1

或者

perl -lane '$k{$_}++ for @F; END{map{print if $k{$_}<2} keys(%k)}' file1 file2

答案2

如果它們按換行符號排序和分隔,您可以使用comm顯示 file1 特有的行:

comm -23 file1 file2

演示:

$ comm -23 <(echo -e 'john\nmike\nanna\npaul\nlaura'|sort) <(echo -e 'john\nmike\npaul'|sort)
anna
laura

或者你可以diff做同樣的事情(grep正在尋找行刪除):

diff sorted-file-1 sorted-file-2 | grep -oP '(?<=< ).+'

如果您需要避免排序或正在處理嚴重的數字,我會轉向合適的語言來進行基於字典的查找。簡單的Python範例:

file2 = {}
with open("file2") as f:
    for line in f:
        file2[line] = 0

with open("file1") as f:
    for line in f:
        if not line in file2:
            print line

任何比這更大的東西,你可能想要查看一個實際的資料庫和一些簡單的 SQL。它們適合大數據。

答案3

還有 python 選項:無論所有單字是在一行還是在單獨的行上:

#!/usr/bin/env python3

import sys

f1 = sys.argv[1]; f2 = sys.argv[2]

def read(f):
    with open(f) as content:
        return content.read().split()

for item in [w for w in read(f1) if not w in read(f2)]:
    print(item)

將腳本複製到一個空文件中,將其另存為showdiff.py使其可執行並透過以下命令運行它:

/path/to/showdiff.py file1 file2

anna
laura

筆記

不是問題,而是聯絡太多,無法遺漏:

如果您需要列出差異相互,(不僅是file1中 中未出現的單字file2,而且是file2中 中未出現的單字file1),應使用以下腳本:

#!/usr/bin/env python3

import sys

f1 = sys.argv[1]; f2 = sys.argv[2]

def read(f):
    with open(f) as content:
        return content.read().split()

wds1 = read(f1); wds2 = read(f2); allwords = wds1+wds2
for item in [w for w in allwords if (w in wds1, w in wds2).count(False) == 1]:
    print(item)

答案4

如果您按照 Jacob Vlijm 建議使用 python 選項,則值得使用“set”(有關更多信息,請參閱https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset)。基本上,一旦創建了兩個集合,您就可以實現集合數學(並集,交集,差異,...)
在這種情況下,集合差異正是您所需要的:一個包含一組中所有元素的新集合,並且不在另一個。
Jacob 的代碼將是:

#!/usr/bin/env python3

import sys

f1 = sys.argv[1]; f2 = sys.argv[2]

def read_set(f):
    with open(f) as content:
        return set(content.read().split())

for item in read_set(f1) - read_set(f2)]:
    print(item)

當然,對於數十億筆記錄來說,還需要一段時間…`

相關內容