수십억 개의 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
이 작업을 완료하면 다음 중 원하는 것을 얻을 수 있습니다.
grep
$ grep -vFwf file2 file1 anna laura
comm
또는diff
$ comm -23 <(sort file1) <(sort file2) anna laura $ diff file1 file2 | grep -Po '<\s+\K.*' anna laura
앗
$ awk '(NR==FNR){a[$1]++; next}!($1 in a){print}' file2 file1 laura anna
펄
$ 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 '(?<=< ).+'
정렬을 피해야 하거나 심각한 숫자를 처리해야 하는 경우 사전 기반 조회를 수행할 수 있는 적절한 언어를 사용하겠습니다. 간단한 파이썬 예:
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)
물론, 수십억 건의 기록에는 시간이 좀 걸릴 것입니다…