i가 아닌 첫 번째 파일에 포함된 이름을 어떻게 얻을 수 있나요?

i가 아닌 첫 번째 파일에 포함된 이름을 어떻게 얻을 수 있나요?

수십억 개의 DNA 서열 이름이 포함된 두 개의 파일이 있는데, 두 번째 파일은 첫 번째 파일의 적절한 하위 집합입니다.

예를 들어,

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

2°:john mike paul ...

모든 이름은 단일 행을 차지합니다.

내 질문은 두 번째 파일에 없는 첫 번째 파일에 포함된 이름을 어떻게 얻을 수 있습니까?

모두 감사합니다!

답변1

이는 매우 간단하지만 공백으로 구분된 목록 대신 한 줄에 하나의 이름이 있으면 생활이 훨씬 더 쉬워집니다. Linux에는 텍스트 파일을 조작하기 위한 훌륭한 유틸리티가 많이 있습니다. 이것은 모든 *nix가 뛰어난 기능 중 하나이지만 대부분은 한 줄에 하나의 항목을 기대합니다. 따라서 대부분의 솔루션은 그에 따라 파일을 수정하는 것으로 시작됩니다.

한 줄에 하나의 이름을 갖도록 파일을 변경하십시오.

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 '(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

줄 바꿈으로 정렬되고 구분된 경우 commfile1에 고유한 줄을 표시할 수 있습니다.

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 '(?<=< ).+'

정렬을 피해야 하거나 심각한 숫자를 처리해야 하는 경우 사전 기반 조회를 수행할 수 있는 적절한 언어를 사용하겠습니다. 간단한 파이썬 예:

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단어도 있음 ), 아래 스크립트를 사용해야 합니다:file2file1

#!/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)

물론, 수십억 건의 기록에는 시간이 좀 걸릴 것입니다…

관련 정보