다음과 같은 파일이 있습니다.
파일 1:
1 2 0.000
1 3 0.213
1 4 0.014
1 5 0.001
1 6 0.555
1 7 0.509
1 8 0.509
3 4 0.995
3 5 0.323
3 6 0.555
3 7 0.225
3 8 0.000
4 5 0.095
4 6 0.058
4 7 0.335
4 8 0.000
5 6 0.995
5 7 0.658
5 8 0.000
6 7 0.431
6 8 0.000
7 8 0.000
파일 2:
1
3
4
5 6 7
파일 2에서 숫자 쌍이 연속적으로 관찰되는 파일 1의 행을 유지하고 싶습니다. 여기서는 파일 2에서 5, 6, 7만 관찰됩니다. 따라서 각 숫자 쌍은 파일 1에 남아 있어야 합니다. 따라서 출력은 다음과 같습니다.
5 6 0.995
5 7 0.658
6 7 0.431
어떤 제안이 있습니까(실제 데이터가 크고 숫자가 1부터 시작하지 않을 수 있다는 점을 고려)?
답변1
perl
해결책이 괜찮다 면 . file1의 컬럼1과 컬럼2 데이터는 컬럼1의 값이 항상 컬럼2보다 작도록 정렬되어 있다고 가정합니다.
$ perl -lane '
if(!$nf)
{
if($#F > 0)
{
foreach $i (0..$#F)
{
$h{"-$F[$i]-$F[$_]-"}++ foreach ($i+1..$#F)
}
}
$nf++ if eof;
}
else
{
print if $h{"-$F[0]-$F[1]-"}
}
' file2 file1
5 6 0.995
5 7 0.658
6 7 0.431
- 먼저, file2에 쌍으로 키의 해시를 구축합니다(다시 숫자가 오름차순이라고 가정).
- 및 대 등 의
-
불일치를 방지하기 위해 두 개의 열 값을 둘러쌉니다 .11
20
1
120
- 및 대 등 의
- 그런 다음 file1 행에 대해 키가 있으면 해당 행을 인쇄하십시오.
file2
로 변경된 경우
$ cat file2
1
3 4
5 6 7 8
$ perl -lane '
if(!$nf)
{
if($#F > 0)
{
foreach $i (0..$#F)
{
$h{"-$F[$i]-$F[$_]-"}++ foreach ($i+1..$#F)
}
}
$nf++ if eof;
}
else
{
print if $h{"-$F[0]-$F[1]-"}
}
' file2 file1
3 4 0.995
5 6 0.995
5 7 0.658
5 8 0.000
6 7 0.431
6 8 0.000
7 8 0.000
답변2
awk를 사용하세요.
첫 번째 awk 명령은 모든 쌍을 포함하는 파일을 생성합니다. 두 번째 awk 명령은 쌍 파일을 배열로 한 번 읽어 일치하는 모든 행을 인쇄합니다.
awk 'NF>1{for(i=1;i<=NF;i++) for(j=i+1;j<=NF;j++) print $i,$j;}' file2 > /tmp/pairs
awk 'BEGIN{while((getline <"/tmp/pairs") > 0) pair[$1,$2]=1; close("/tmp/pairs")} ($1,$2) in pair' file1
두 번째 명령에는 많은 메모리가 필요할 수 있습니다! 파일이 순서대로 정렬되어 있으면 어떻게든 배열을 피하고 두 파일을 동시에 읽을 수 있습니다. 최종 실행 전에 쌍 파일을 보려면 두 가지 명령을 사용합니다.
여기의 코드는 단일 명령과 동일하며 읽을 수 있는 형식입니다.
awk '
BEGIN {
f="file2"
while((getline <f) > 0)
for(i=1;i<=NF;i++)
for(j=i+1;j<=NF;j++)
pair[$i,$j]=1;
close(f);
}
($1,$2) in pair
' file1
참고로file1(22 mill.lines), file2(4 mill.lines)에 대해 일부 벤치마크를 실행하여 2 mill.lines를 생성했습니다. 라인 출력.
- gawk: 9.6초, 275M 메모리
- mawk: 20.7초, 134M 메모리
- Sundeep의 Perl 답변: 31.9초, 231M 메모리