여러 번 나타나는 열 식별자와 고유 행을 포함하는 두 테이블 병합

여러 번 나타나는 열 식별자와 고유 행을 포함하는 두 테이블 병합

어제도 비슷한 질문을 했습니다(여러 번 나타나는 열 식별자를 포함하는 두 테이블 병합) 그러나 고유한 줄 문제에 직면했습니다.

열 1을 기준으로 두 테이블을 병합하고 싶습니다.

파일 1:

1 오늘
1 녹색
2 내일
3 빨간색

파일 2:

1 많이
1 가끔
2 직장에서
2 집에서
2 가끔
3 새로운
4 많이
5 가끔
6 직장에서

예상 출력(파일 3):

1 오늘 많이
1 오늘 가끔
1 녹색 가끔 많이
1 녹색 가끔
2 내일 출근
2 내일 집에서
2 내일 가끔
3 빨간색 새

나는 다음을 생각해 냈습니다.

awk -F '[\t]' -v OFS='\t' '{i=$1;$1=x} NR==FNR{A[i]=$0;next} A[i]{print i,$0A[i]}' file2 file1 > file3

그러나 그것은 나에게만 제공합니다:

1 오늘 가끔
2 가끔 내일
3 빨간색 새

이전 스레드(join 및 awk)의 솔루션은 두 파일의 조합(모든 행 포함)을 제공합니다. 파일 1의 행(열 1을 식별자로)만 포함하고 싶지만 파일 2의 모든 일치 항목을 보고합니다.

편집하다:

탭으로 구분된 열

실제 파일 1: fig|395961.4.peg.2627 박테리아 남세균 알 수 없음 알 수 없음 1795

(1열: 그림...2열: 박테리아...3열 1795)

실제 파일 2: fig|1000561.3.peg.1838 시스테인 탈황효소(EC 2.8.1.7) 테스트 - 티아민 보조인자, 비타민, 보결분자단, 색소

(1열: 그림...2열: 시스테인...3열 테스트...)

답변1

나는 Perl에서 이것을 할 것이다:

#!/usr/bin/env perl 
use strict;

my (%file1,%file2);

## Open the 1st file
open(A,"file1");
while(<A>){
    ## Remove trailing newlines
    chomp; 
    ## Split the current line on tabs into the @F array.
    my @F=split(/\t/); 
    ## This is the tricky part. It adds fields 2-last
    ## to the hash $file1. The value of this hash is an array
    ## and the keys are the 1st fields. This will result in a list
    ## of all 1st fields and all their associated columns.
    push @{$file1{$F[0]}},@F[1..$#F];
} 


## Open the 2nd file
open(B,"file2");
while(<B>){
    ## Remove trailing newlines
    chomp; 
    ## Split the current line on tabs into the @F array.
    my @F=split(/\t/); 

    ## If the current 1st field was found in file1
    if (defined($file1{$F[0]})) {
        ## For each of the columns associated with
        ## this 1st field in the 1st file.
        foreach my $col (@{$file1{$F[0]}}) {
            print "$F[0]\t$col\t@F[1..$#F]\n";
        }
    }
} 

(긴) 한 줄에 입력할 수 있습니다.

$ perl -lane 'BEGIN{open(A,"file1"); while(<A>){chomp; @F=split(/\t/); 
                    push @{$k{$F[0]}},@F[1..$#F];}  } 
              $k{$F[0]} && print "$F[0]\t@{$k{$F[0]}}\t@F[1..$#F]"' file2
1   today green a lot
1   today green sometimes
2   tomorrow    at work
2   tomorrow    at home
2   tomorrow    sometimes
3   red new

대용량 파일로 작업하는 경우 잠시 동안 실행해 보세요.

답변2

awk를 사용하세요

기능 사용

명확하고 읽기 쉬움:

    awk 'function get(file,x,y) {
        while ( (getline < file) > 0) {if ($1==x)y,substr($0,index($0," ")+1)}
        close(file)
        }
        ARGV[1]==FILENAME{get(ARGV[2],$1,$0)}' file1 file2

하나의 선:

awk 'function g(f,x,y){while((getline <f)>0)if($1==x){print y,substr($0,index($0," ")+1)}close(f)}NR==FNR{g(ARGV[2],$1,$0)}' file1 file2

.

배열 사용

awk 'FNR==NR{a[$0]=$1;next}{for(i in a)if(a[i]==$1)print i,substr($0,index($0," ")+1)}' file file2

.

결과

1 today a lot
1 today sometimes
1 green a lot
1 green sometimes
2 tomorrow at work
2 tomorrow at home
2 tomorrow sometimes
3 red new

답변3

Join 명령에 어떤 문제가 있습니까?

파일 1 파일 2 추가

원하는 결과를 제공합니다

관련 정보