두 개의 파일(단일 열)이 있는 경우 하나는 다음과 같습니다(파일 1)
34
67
89
92
102
180
blue2
3454
두 번째 파일(file2)
23
56
67
69
102
200
두 파일에 공통된 요소(교차점)를 찾는 방법은 무엇입니까? 이 예에서 예상되는 출력은 다음과 같습니다.
67
102
파일마다 항목 수(행 수)가 다르므로 주의하세요. 숫자와 문자열이 혼합될 수 있습니다. 반드시 정렬되지는 않을 수도 있습니다. 각 항목은 한 번만 나타납니다.
고쳐 쓰다:
시간 확인아래의 몇 가지 답변을 바탕으로 합니다.
# generate some data
>shuf -n2000000 -i1-2352452 > file1
>shuf -n2000000 -i1-2352452 > file2
#@ilkkachu
>time (join <(sort "file1") <(sort "file2") > out1)
real 0m15.391s
user 0m14.896s
sys 0m0.205s
>head out1
1
10
100
1000
1000001
#@Hauke
>time (grep -Fxf "file1" "file2" > out2)
real 0m7.652s
user 0m7.131s
sys 0m0.316s
>head out2
1047867
872652
1370463
189072
1807745
#@Roman
>time (comm -12 <(sort "file1") <(sort "file2") > out3)
real 0m13.533s
user 0m13.140s
sys 0m0.195s
>head out3
1
10
100
1000
1000001
#@ilkkachu
>time (awk 'NR==FNR { lines[$0]=1; next } $0 in lines' "file1" "file2" > out4)
real 0m4.587s
user 0m4.262s
sys 0m0.195s
>head out4
1047867
872652
1370463
189072
1807745
#@Cyrus
>time (sort file1 file2 | uniq -d > out8)
real 0m16.106s
user 0m15.629s
sys 0m0.225s
>head out8
1
10
100
1000
1000001
#@Sundeep
>time (awk 'BEGIN{while( (getline k < "file1")>0 ){a[k]}} $0 in a' file2 > out5)
real 0m4.213s
user 0m3.936s
sys 0m0.179s
>head out5
1047867
872652
1370463
189072
1807745
#@Sundeep
>time (perl -ne 'BEGIN{ $h{$_}=1 while <STDIN> } print if $h{$_}' <file1 file2 > out6)
real 0m3.467s
user 0m3.180s
sys 0m0.175s
>head out6
1047867
872652
1370463
189072
1807745
Perl 버전이 가장 빠르며 그 다음은 awk입니다. 모든 출력 파일의 행 수는 동일합니다.
비교를 위해 출력이 동일하도록 출력을 숫자순으로 정렬했습니다.
#@ilkkachu
>time (join <(sort "file1") <(sort "file2") | sort -k1n > out1)
real 0m17.953s
user 0m5.306s
sys 0m0.138s
#@Hauke
>time (grep -Fxf "file1" "file2" | sort -k1n > out2)
real 0m12.477s
user 0m11.725s
sys 0m0.419s
#@Roman
>time (comm -12 <(sort "file1") <(sort "file2") | sort -k1n > out3)
real 0m16.273s
user 0m3.572s
sys 0m0.102s
#@ilkkachu
>time (awk 'NR==FNR { lines[$0]=1; next } $0 in lines' "file1" "file2" | sort -k1n > out4)
real 0m8.732s
user 0m8.320s
sys 0m0.261s
#@Cyrus
>time (sort file1 file2 | uniq -d > out8)
real 0m19.382s
user 0m18.726s
sys 0m0.295s
#@Sundeep
>time (awk 'BEGIN{while( (getline k < "file1")>0 ){a[k]}} $0 in a' file2 | sort -k1n > out5)
real 0m8.758s
user 0m8.315s
sys 0m0.255s
#@Sundeep
>time (perl -ne 'BEGIN{ $h{$_}=1 while <STDIN> } print if $h{$_}' <file1 file2 | sort -k1n > out6)
real 0m7.732s
user 0m7.300s
sys 0m0.310s
>head out1
1
2
3
4
5
이제 모든 출력이 동일합니다.
답변1
단순한comm
+sort
해결책:
comm -12 <(sort file1) <(sort file2)
-12
- 공통 행(두 파일 모두에서 발생)만 출력되도록 열1
합계(및 각각 고유 행 )를 억제합니다.2
FILE1
FILE2
답변2
에서는 awk
첫 번째 파일을 메모리에 완전히 로드합니다.
$ awk 'NR==FNR { lines[$0]=1; next } $0 in lines' file1 file2
67
102
또는 특정 행이 발생하는 횟수를 추적하려는 경우:
$ awk 'NR==FNR { lines[$0] += 1; next } lines[$0] {print; lines[$0] -= 1}' file1 file2
join
이 작업을 수행할 수 있지만 입력 파일을 정렬해야 하므로 먼저 정렬해야 하며 그렇게 하면 원래 순서가 손실됩니다.
$ join <(sort file1) <(sort file2)
102
67
답변3
앗
awk 'NR==FNR { p[NR]=$0; next; }
{ for(val in p) if($0==p[val]) { delete p[val]; print; } }' file1 file2
이는 (대형 파일의 경우) 동일한 항목을 여러 번 인쇄하고 일치 후 항목을 다시 확인하는 것을 생략하므로 가장 빠르기 때문에 좋은 솔루션입니다.
grep
grep -Fxf file1 file2
동일한 항목이 에 여러 번 나타나면 여러 번 출력됩니다 file2
.
유형
재미삼아 (보다 훨씬 느려야 함 grep
):
sort -u file1 >t1
sort -u file2 >t2
sort t1 t2 | uniq -d
답변4
약간 다르고 awk
동등한 perl
버전
3회 연속으로 보고서를 실행하는 데 걸리는 시간
$ # just realized shuf -n2000000 -i1-2352452 can be used too ;)
$ shuf -i1-2352452 | head -n2000000 > f1
$ shuf -i1-2352452 | head -n2000000 > f2
$ time awk 'NR==FNR{a[$1]; next} $0 in a' f1 f2 > t1
real 0m3.322s
real 0m3.094s
real 0m3.029s
$ time awk 'BEGIN{while( (getline k < "f1")>0 ){a[k]}} $0 in a' f2 > t2
real 0m2.731s
real 0m2.777s
real 0m2.801s
$ time perl -ne 'BEGIN{ $h{$_}=1 while <STDIN> } print if $h{$_}' <f1 f2 > t3
real 0m2.643s
real 0m2.690s
real 0m2.630s
$ diff -s t1 t2
Files t1 and t2 are identical
$ diff -s t1 t3
Files t1 and t3 are identical
$ du -h f1 f2 t1
15M f1
15M f2
13M t1